SAM Example 3B
From SoOS
Contents |
[edit] Description
This example shows how to execute speculatively and flash back a worker thread (efficient version).
[edit] Code
#include <stdio.h>
#include <stdlib.h>
#include <sam.h>
#define N 4
#define ARRAY_SIZE 64
struct datast
{
int *A;
};
void * worker_routine(void *args)
{
SAM_t sam_context; /* Declare a SAM context variable */
void *myargs; /* Pointer to where the arguments are stored */
int *myArray; /* Pointer to the Array of the data */
struct datast *data_arg; /* Pointer to the arguments of the function */
int total; /* Store the variable of the calculation */
int *result; /* Pointer to the result (total) of the calculation */
int i;
/* Start the execution of this worker thread */
/* Extract the SAM context and the arguments */
SAM_Execution_start(args, &sam_context, &myargs);
/* Print the SAM worker ID of this worker thread */
printf("SAM worker id: %d\n", (int)SAM_My_workid(sam_context));
/* Extract the arguments of the function */
data_arg = (struct datast *) myargs;
myArray = data_arg->A;
total = 0;
/* Declare the region as read by the worker thread */
SAM_Memory_speculative_read(sam_context, SAM_My_workid(sam_context), myArray);
/* Make some calculations... */
for(i=0; i<ARRAY_SIZE; i++)
{
total += myArray[i];
}
total = total * (int)SAM_My_workid(sam_context);
/* Print the total, but this value might not be valid */
printf("Calculated %d: %d\n", (int)SAM_My_workid(sam_context), total);
/* Finish the execution of this worker trhead */
SAM_Execution_finish(sam_context);
/* Reserve memory for the result and return it */
result = (int *) malloc(sizeof(int));
*result = total;
return result;
}
int main(void)
{
SAM_t sam_context; /* Declare a SAM context variable */
SAM_Workerid_t th[N]; /* For storing the worker threads ID's */
int *result; /* Gets the result of the worker thread */
int *myArray; /* Pointer to the array of the data */
struct datast *data_arg; /* Pointer to the worker threads arguments */
int i;
myArray = (int *) malloc(ARRAY_SIZE *sizeof(int));
data_arg = (struct datast *) malloc(sizeof(struct datast));
/* Set some data into the Array */
for(i=0; i<ARRAY_SIZE; i++)
{
myArray[i] = i + 1000;
}
/* Initialize the SAM context */
SAM_Init(&sam_context);
/* Setup the arguments we are going to send to the worker threads */
data_arg->A = myArray;
/* Register a region and protect it */
SAM_Memory_region_register(sam_context, myArray, ARRAY_SIZE * sizeof(int));
SAM_Memory_region_protect(sam_context, myArray);
for(i=0;i<N;i++)
{
/* Create the worker threads running worker_routine */
th[i] = SAM_Execution_create(sam_context, *worker_routine, (void *)data_arg);
}
/* ---------------------------------------- */
/* Prepare the region to write, this flashes back all the worker threads */
/* that already acceded to this region of memory */
SAM_Memory_write_prepare(sam_context, myArray);
for(i=0; i<ARRAY_SIZE; i++)
{
/* Create a delay to allow some context switches */
usleep(20*1000);
/* Set a new value in the array elements*/
myArray[i] = i;
}
/* Declare the region as written */
SAM_Memory_write(sam_context, myArray);
/* ---------------------------------------- */
for(i=0;i<N;i++)
{
/* Join the worker threads and get the result */
result = (int *)SAM_Execution_join(sam_context, th[i]);
/* Print the result */
printf("RES %d: %d\n", i, *result);
/* Do not forget to free the memory reserved to store the result */
free(result);
}
/* Release and unregister the memory region*/
SAM_Memory_region_release(sam_context, myArray);
SAM_Memory_region_unregister(sam_context, myArray);
/* Destroy the SAM context */
SAM_Destroy(&sam_context);
/* Free the memory */
free(myArray);
free(data_arg);
return 0;
}
[edit] Explanation
This example shows how to register a region, protect it, read from it speculatively and flash back a worker thread when needed, but in a more efficient way than in Example 3 A.
Example 3 A creates many flashbacks, this can be improved as shown in this example. The main differences are that the call to SAM_Memory_write() is situated outside the if loop that is writing continuously to the protected memory region (line 112). This way the worker threads are only flashed back once, after finishing all the modifications. Also, in line 103, SAM_Memory_write_prepare() is called, to halt access to worker threads to this memory region.
[edit] Compile Command
gcc example3b.c -lsam -lpthread -o example3b