0

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_count field represents the amount of block that has to be treated,
  • The th_blk_size field represents the size of a block,
  • The th_blk_current field represents the processed block (they are listed from 0 to n),
  • The th_blk_i_start is 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?

0

1 Answer 1

1

I think the problem here is that you think the thread gets passed a copy of the structure. It doesn't, it gets a pointer. All the threads get a pointer to the same structure. So any changes to the structure will affect all threads.

You need to come up with a way to pass individual data to the individual threads. For example a thread-specific structure containing only the thread-specific data, and you dynamically allocate an instance of that structure to pass to the thread.

Sign up to request clarification or add additional context in comments.

1 Comment

I think the problem here is that you think the thread gets passed a copy of the structure. No, I know that it is not a copy. But I didn't figured it out. Tired .... Thanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.