What is the best way to end several task running within a par() ?
I have several tasks running inside a par()
One of the tasks (master) has a for loop that will be finished after some time. When that task is finished I would like all other parallel task to stop as well, and the main program to continue to the next par.
par{
master(channels);
slave_1(channels);
slave_2(channels);
slave_3(channels);
slave_4(channels);
}
par{
another_master(.....
Ending/stopping a parrallel task and how to restart tasks
-
- XCore Expert
- Posts: 956
- Joined: Fri Dec 11, 2009 3:53 am
- Location: Sweden, Eskilstuna
Ending/stopping a parrallel task and how to restart tasks
Probably not the most confused programmer anymore on the XCORE forum.
-
- Experienced Member
- Posts: 94
- Joined: Tue Apr 27, 2010 10:55 pm
Send a message through a channel to to tell them that they should cancel. This would be a clean design IMHO.
-
- XCore Expert
- Posts: 956
- Joined: Fri Dec 11, 2009 3:53 am
- Location: Sweden, Eskilstuna
How do I send a message through a channel, without the use of 7 channels if I have 7 slave processes?skoe wrote:Send a message through a channel to to tell them that they should cancel. This would be a clean design IMHO.
A channel must have only 2 channel ends. I would need 7 different channels in the master.
Can it be done in some daisy chain? The stop signal travels from the master to the first slave - from first slave to second slave and so on.
I cannot afford using up 7 channels just for a stop token.
There is some functions for control tokens. Can I use them ?
outct Streams out a control token on a channel end
Probably not the most confused programmer anymore on the XCORE forum.
-
- Experienced Member
- Posts: 94
- Joined: Tue Apr 27, 2010 10:55 pm
Yes, I meant one channel per thread. AFAIK there's nothing like a broadcast/multicast in XMOS, so you'd need to use a loop over the channels. Technically you can use one channel end to address all channel ends of the the slave threads, one by one.
I don't know if XC supports this. If not you can use inline assembly to take one channel end, set its destination to the others (setd) and send data or a control token (out/outct) to each of them in a loop. This is one of the things that makes XC look a bit unhandy to me, but maybe I didn't find the trick yet and it's possible without inline assembly.
I don't know if XC supports this. If not you can use inline assembly to take one channel end, set its destination to the others (setd) and send data or a control token (out/outct) to each of them in a loop. This is one of the things that makes XC look a bit unhandy to me, but maybe I didn't find the trick yet and it's possible without inline assembly.
-
- Member
- Posts: 13
- Joined: Fri Dec 11, 2009 10:51 am
7 channels would be the clean way. I like to call the technique poisoning - a control token is the posion and each thread passes the token to the next thread, so eventually all threads will die.
Bear in mind there are 32 channel ends on each core and you can reuse them in the next par.
If that's still too much, just use a shared variable:
where ptr gives you the address of stop (compiled in a separate C file):
Bear in mind there are 32 channel ends on each core and you can reuse them in the next par.
If that's still too much, just use a shared variable:
Code: Select all
void masterr(int stop_ptr)
{
asm("stw %0, %1[0]" :: "r"(1), "r"(stop_ptr));
}
void slavee(int stop_ptr)
{
int stop;
do {
asm("ldw %0, %1[0]" : "=r"(stop) : "r"(stop_ptr));
} while (!stop);
}
int ptr(const int &var);
int main()
{
int stop = 0;
par {
masterr(ptr(stop));
slavee(ptr(stop));
slavee(ptr(stop));
}
return 0;
}
Code: Select all
int ptr(const int *var)
{
return (int)var;
}
-
- XCore Expert
- Posts: 956
- Joined: Fri Dec 11, 2009 3:53 am
- Location: Sweden, Eskilstuna
To make it easier to read I solved it with a struct like this.
A function like this:
And in the main it looks like this:
The program passes Step1 and Step2, but stops in the second par.
In debug mode I can find the stopping point.
The I2S_slave has stopped at:
(c_ADC = @0x1deb8)
And the lmsfind has stopped at
(c_IN = @0x1deb8)
Somehow the states of the channels are not the same the second time compared to the first time.
How do i terminate/reset or solve the issue :?: :?: :?:
It's 2 channel ends of the same channels - why is it locked ??
Code: Select all
typedef const struct{
unsigned int run;
unsigned int mode;
}control_struct;
Code: Select all
void enable(control_struct &control,unsigned int mode){
control.run=1;
control.mode=mode;
return;
}
Code: Select all
enable(control,0);
par
{
I2S_slave(c_DAC , c_ADC , control);
lmsfind(c_ADC,c_DAC ,W0, FXfir_L , control);
}
enable(control,1);
printstr("\nStep2\n");
par
{
I2S_slave(c_DAC , c_ADC , control);
lmsfind(c_ADC , c_DAC , W1, FXfir_R, control);
}
printstr("Step3\n");
In debug mode I can find the stopping point.
The I2S_slave has stopped at:
Code: Select all
c_ADC[0]<:(TEMP_ADC);
And the lmsfind has stopped at
Code: Select all
c_IN[0] :> Y;
Somehow the states of the channels are not the same the second time compared to the first time.
How do i terminate/reset or solve the issue :?: :?: :?:
It's 2 channel ends of the same channels - why is it locked ??
Probably not the most confused programmer anymore on the XCORE forum.
-
- XCore Legend
- Posts: 1274
- Joined: Thu Dec 10, 2009 10:20 pm
I'm guessing c_DAC , c_ADC are channels?
If so they can have only 2 endpoints. by trying to reuse them in the second Par you are effectively trying to add new endpoints I think. Try using new channels in the second par.
*Update - Sorry I'm obviously not paying attention, you seem to be using arrays of channels, Thus I cannot see if these are being globally declared/reused or what. But it could be that you are trying to assign/reassign more than 2 endpoints to one or more of the channels.
regards
Al
If so they can have only 2 endpoints. by trying to reuse them in the second Par you are effectively trying to add new endpoints I think. Try using new channels in the second par.
*Update - Sorry I'm obviously not paying attention, you seem to be using arrays of channels, Thus I cannot see if these are being globally declared/reused or what. But it could be that you are trying to assign/reassign more than 2 endpoints to one or more of the channels.
regards
Al
-
- XCore Expert
- Posts: 956
- Joined: Fri Dec 11, 2009 3:53 am
- Location: Sweden, Eskilstuna
Ahaa, it's an array but I use the same channels in the array in both par.Folknology wrote:I'm guessing c_DAC , c_ADC are channels?
If so they can have only 2 endpoints. by trying to reuse them in the second Par you are effectively trying to add new endpoints I think. Try using new channels in the second par.
*Update - Sorry I'm obviously not paying attention, you seem to be using arrays of channels, Thus I cannot see if these are being globally declared/reused or what. But it could be that you are trying to assign/reassign more than 2 endpoints to one or more of the channels.
regards
Al
(The second par doesn't start before the functions from the first par is terminated.)
Can I "kill" channels in XC and reuse them later, or do I need to use ASM or something from the xs1.h like start_streaming / stop streaming?
Probably not the most confused programmer anymore on the XCORE forum.
-
- XCore Legend
- Posts: 1274
- Joined: Thu Dec 10, 2009 10:20 pm
I wondered if you could put the chan declarations inside the Par block to limit scope but that's now allowed, I'm not even sure its really a block per se rather a syntactical convenience.
So the questions becomes can one reuse/recycle channels?
So the questions becomes can one reuse/recycle channels?
-
- XCore Legend
- Posts: 1274
- Joined: Thu Dec 10, 2009 10:20 pm
I should also point out that you are on a bit of a sticky wicket:
1) You are not allocating threads to a core "on stdcore[x] : ...." this is dicouraged as eventually may not be allowed.
2) When you do allocate threads to cores you will not be able to use multiple par statements in Main try it.
Over all maybe another pattern may be more suitable to your problem, I might be tempted to perhaps use a Replicator with a much higher abstraction, that would mean making your thread functions more generic, but capable of morphing based on channel signalling perhaps and or via a mode integer passed in through the replicator index or derivative thereof. A combination of these techniques may likely even be required.
But to be fair at this point I do not fully understand the exact problem that you are trying to solve so I may be spouting nonsense ;-)
regards
Al
1) You are not allocating threads to a core "on stdcore[x] : ...." this is dicouraged as eventually may not be allowed.
2) When you do allocate threads to cores you will not be able to use multiple par statements in Main try it.
Over all maybe another pattern may be more suitable to your problem, I might be tempted to perhaps use a Replicator with a much higher abstraction, that would mean making your thread functions more generic, but capable of morphing based on channel signalling perhaps and or via a mode integer passed in through the replicator index or derivative thereof. A combination of these techniques may likely even be required.
But to be fair at this point I do not fully understand the exact problem that you are trying to solve so I may be spouting nonsense ;-)
regards
Al