I have a problem for accessing an array from several threads. I have written a struct which gathers all informations needed for the job I want to do.
The structure is defined like this:
struct thread_blk
{
size_t th_blk_count;
size_t th_blk_size;
size_t th_blk_current;
size_t* th_blk_i_start;
void* data;
pthread_t* th_id;
ThreadBlockAdaptive th_blk_adapt;
};
The idea is to fill an array from multiple threads, each one working on a delimited field of memory of an array.
- The
th_blk_countfield represents the amount of block that has to be treated, - The
th_blk_sizefield represents the size of a block, - The
th_blk_currentfield represents the processed block (they are listed from0ton), - The
th_blk_i_startis an array which contains indexes of the array that has to be filled.
Just a single function applied to the thread_blk struct is not working properly:
int startAllThreadBlock(struct thread_blk* th_blk, worker_func f)
{
int res = 0;
for(size_t i = 0; i < th_blk->th_blk_count; ++i)
{
res |= pthread_create(th_blk->th_id + i, NULL, f, th_blk);
th_blk->th_blk_current++;
}
return res;
}
In fact, the th_blk_current field is not incremented properly. I used it to retrieve the th_blk_i_start indexes which serve as intervals. As a result, my worker (shown bellow) is processing the same indexes of the double array.
Here is the function I use in the startAllThreadBlock function:
void* parallel_for(void* th_blk_void)
{
ThreadBlock th_blk = (ThreadBlock)th_blk_void;
size_t i = getThreadBlockStartIndex(th_blk, getThreadBlockCurrentIndex(th_blk));
printf(
"Running thread %p\n"
" -Start index %zu\n\n",
pthread_self(),
i
);
if(getThreadBlockCurrentIndex(th_blk) == (getThreadBlockCount(th_blk) - 1))
{
for(; i < MAX; ++i)
{
result[i] = tan(atan((double)i));
}
}
else
{
size_t threshold = getThreadBlockStartIndex(th_blk, getThreadBlockCurrentIndex(th_blk) + 1);
for(; i < threshold; ++i)
{
result[i] = tan(atan((double)i));
}
}
return NULL;
}
ThreadBlock is just a typedef over a thread_blk*; result is the array of double.
I am pretty sure that the problem lies around the startAllThreadBlock (if I use a 1 second sleep everything run as expected). But I don't know how to fix it.
Does someone have an idea?
Thanks for your answers.
Update
Placing the incrementation in the worker solved the problem. But I think it is not safe though, for the reason Some programmer dude mentioned.
void* parallel_for(void* th_blk_void)
{
ThreadBlock th_blk = (ThreadBlock)th_blk_void;
size_t i = getThreadBlockStartIndex(th_blk, getThreadBlockCurrentIndex(th_blk));
size_t n;
if(getThreadBlockCurrentIndex(th_blk) == (getThreadBlockCount(th_blk) - 1))
{
n = MAX;
}
else
{
n = getThreadBlockStartIndex(th_blk, getThreadBlockCurrentIndex(th_blk) + 1);
}
incThreadBlockCurrent(th_blk);
printf(
"Running thread %p\n"
" -Start index %zu\n\n",
pthread_self(),
i
);
for(; i < n; ++i)
{
result[i] = tan(atan((double)i));
}
return NULL;
}
It would do it with a mutex on th_blk_current no?