Channels in two threads only but compiler says they are not Topic is solved

If you have a simple question and just want an answer.
BaBristol
New User
Posts: 3
Joined: Sat Nov 26, 2016 3:33 pm

Channels in two threads only but compiler says they are not

Post by BaBristol »

Hello,

I am currently working on a parallel game of life implementation which can use any number of workers (understand threads which simulate a tick for a portion of the image) as long as it is a square number. To achieve such a goal I need to automatically generate those n workers in function of the constant number of workers defined in the code in addition to generate and assign channels for between worker communications. I achieve this using two nested par loops, but here the compilers output errors saying I am using channels in more than two threads, when I am definitely not, because if I create the workers manually using the same reasoning for the attributions of the channels, it compiles! Everything may be a bit abstract, that is why I will try to give you some code samples. Here is the worker signature:

Code: Select all

void worker(int const xID, int const yID, chanend c, //Not relevant for this problem
chanend up, chanend down, chanend left, chanend right) //Represent the channels between neighbouring workers.
To automatically assign the channels, I use a three dimensional array as follow:

Code: Select all

chan betweenWorkersChannel[SQRT_AVAILABLE_WORKERS_THREAD][SQRT_AVAILABLE_WORKERS_THREAD][2];
It is when things become tricky, to assign the channels to each workers, I use the following rule: If the sum of the indices of a worker is even (for example (0, 0) or (1, 1)) then the array will contains the channels for the specified worker with its upper and below neighbour (in this order! i.e. [0] is upper channel and [1] is downward channel). In case of an odd one, the array will contains the channels for left and right communications (in this order again). I summarised this in a picture involving 4 workers, where the colour red means a worker "owns" the channel where blue means it does not. You can see each worker indexes in parenthesis (x,x) and four examples of channel uses in the array [x][y][up/down/left/right].
Image

Now I have explained how my system works, here is the portion of code generating the workers and not passing the compiler checks:

Code: Select all

par (size_t i = 0; i < SQRT_AVAILABLE_WORKERS_THREAD; ++i) {
    par (size_t j = 0; j < SQRT_AVAILABLE_WORKERS_THREAD; ++j) {
        //Create and start worker
        if((i+j)%2 == 0){
            worker(i, j, channels[i][j], betweenWorkersChannel[i][j][0], betweenWorkersChannel[i][j][1], betweenWorkersChannel[i][(j-1+ SQRT_AVAILABLE_WORKERS_THREAD)% SQRT_AVAILABLE_WORKERS_THREAD][1], betweenWorkersChannel[i][(j+1+ SQRT_AVAILABLE_WORKERS_THREAD)% SQRT_AVAILABLE_WORKERS_THREAD][0]);
        }
        else{
            worker(i, j, channels[i][j], betweenWorkersChannel[(i-1 + SQRT_AVAILABLE_WORKERS_THREAD)% SQRT_AVAILABLE_WORKERS_THREAD][j][1], betweenWorkersChannel[(i+1+ SQRT_AVAILABLE_WORKERS_THREAD)% SQRT_AVAILABLE_WORKERS_THREAD][j][0], betweenWorkersChannel[i][j][0], betweenWorkersChannel[i][j][1]);
        }
    }
}
And here is the hard coded working workers using the same technique:

Code: Select all

worker(0, 0, channels[0][0], betweenWorkersChannel[0][0][0], betweenWorkersChannel[0][0][1], betweenWorkersChannel[0][1][1], betweenWorkersChannel[0][1][0]);
worker(1, 1, channels[1][1], betweenWorkersChannel[1][1][0], betweenWorkersChannel[1][1][1], betweenWorkersChannel[1][0][1], betweenWorkersChannel[1][0][0]);
worker(0, 1, channels[0][1], betweenWorkersChannel[1][1][1], betweenWorkersChannel[1][1][0], betweenWorkersChannel[0][1][0], betweenWorkersChannel[0][1][1]);
worker(1, 0, channels[1][0], betweenWorkersChannel[0][0][1], betweenWorkersChannel[0][0][0], betweenWorkersChannel[1][0][0], betweenWorkersChannel[1][0][1]);
Could someone help me with this problem please?

Thank you very much for your help and sorry if everything seems a bit confusing, I tried to do my best to explain you my system, do not hesitate to ask me to explain something further!
View Solution
User avatar
mon2
XCore Legend
Posts: 1913
Joined: Thu Jun 10, 2010 11:43 am

Post by mon2 »

Hi. Not fully aware of the par construct details as we have not used them in the style you have posted but a few thoughts..

1) What is the value of SQRT_AVAILABLE_WORKERS_THREAD ?

2) If you assign SQRT_AVAILABLE_WORKERS_THREAD = 1, does the compiler still complain ?

3) Which processor are you using ? Respectively, review the datasheet for the max # of threads (cores) allowed for your target processor (will vary from 4 to 16 threads per tile).

Review this webpage to be sure the par construct is being applied correctly:

https://www.xmos.com/published/xmos-pro ... =B&page=23

See Replicated par statements

Specifically, review the max # of threads you can run with par construct for your CPU.
BaBristol
New User
Posts: 3
Joined: Sat Nov 26, 2016 3:33 pm

Post by BaBristol »

Thank you both for your replies!
mon2 wrote: 1) What is the value of SQRT_AVAILABLE_WORKERS_THREAD ?

2) If you assign SQRT_AVAILABLE_WORKERS_THREAD = 1, does the compiler still complain ?

3) Which processor are you using ? Respectively, review the datasheet for the max # of threads (cores) allowed for your target processor (will vary from 4 to 16 threads per tile).
1) It is the square root of the number of worker (which is always a square number), in my example, it is 2.

2) I am not sure of the behaviour of the program with only 1 worker, I will have to figure it out.

3)I am using a xcore-200 eXploreKit, but with 4 workers, the number of threads and channels are less than the maximum number of threads.
henk wrote:Hi,

I would expect the channel going left to be always [j][0], and the channel to the top always [j][1], the channel tot he right always [(j+1)%...][0], and the channel to the bottom always [(i+1)%...][j][1].

In that case you won't need the IF statement? (I expect the IF statement to cause trouble by the way - I don't think the compiler is required to constant propagate the IF away, leading to two potential uses of worker().)

Cheers,
Henk


This seems a possible solution! I will try it and come back to tell you how it is going with that solution. My first thought was indeed that the compiler fails to consider the if.
henk
Verified
Respected Member
Posts: 347
Joined: Wed Jan 27, 2016 5:21 pm

Post by henk »

Hi,

I would expect the channel going left to be always [j][0], and the channel to the top always [j][1], the channel tot he right always [(j+1)%...][0], and the channel to the bottom always [(i+1)%...][j][1].

In that case you won't need the IF statement? (I expect the IF statement to cause trouble by the way - I don't think the compiler is required to constant propagate the IF away, leading to two potential uses of worker().)

Cheers,
Henk
BaBristol
New User
Posts: 3
Joined: Sat Nov 26, 2016 3:33 pm

Post by BaBristol »

Thank you very much henk, it works perfectly!