www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - can I force a parallel foreach to finish?

reply "McAnany, Charles E" <mcanance rose-hulman.edu> writes:
SGksIGFsbC4gU28gSSdtIGdldHRpbmcgdGhlIGNsYXNzaWMgImNvbmN1cnJlbmN5IG5vb2IiIGJl
aGF2aW9yIGZyb20gdGhpcyBjb2RlOg0KICAgIHNoYXJlZCBpbnQgdGltZXM7ICAgIA0KICAgIGlu
dFtdIGl0ZXJhdGlvblJhbmdlID0gbmV3IGludFsyNTAwXTsNCiAgICBmb3JlYWNoIChwb3MsIHJl
ZiAgaTsgcGFyYWxsZWwoaXRlcmF0aW9uUmFuZ2UpKXsNCiAgICAgICAgdGltZXMrKzsNCiAgICB9
DQogICAgd3JpdGVsbih0aW1lcyk7DQp9DQpQcmludHMgcmFuZG9tIG51bWJlcnMgbmVhciAxLDAw
MC4NCkxvb2tpbmcgYXQgdGhlIGRvY3VtZW50YXRpb24gZm9yIHN0ZC5jb25jdXJyZW5jeSwgaXQg
YXBwZWFycyB0aGF0IHdoZW4gZGVhbGluZyB3aXRoIHRhc2tzLCB5b3UgaGF2ZSB0byB5aWVsZEZv
cmNlIHRvIGdldCB0aGVtIHRvIGZpbmlzaC4gSXMgdGhlcmUgYSBtZXRob2QgdGhhdCBibG9ja3Mg
dW50aWwgdGFza1Bvb2wgaXRzZWxmIGlzIGVtcHR5Pw0KDQpJIHRoaW5rIHRoZSBwcm9ibGVtIGlz
IG5vdCBjb25jdXJyZW50IG1vZGlmaWNhdGlvbiwgdGhlIGZvcmVhY2gganVzdCBzZWVtcyB0byBy
ZXR1cm4gdG9vIGVhcmx5LCBhcyBzZWVuIGhlcmU6DQoNCmludCB0aW1lczsNCnZvaWQgc2hhcmVB
dWdtZW50ZXIoKXsNCiAgICBib29sIGNvbnQgPSB0cnVlOw0KICAgIHdoaWxlKGNvbnQpew0KICAg
ICAgICByZWNlaXZlKCAoaW50IGkpe3RpbWVzKys7fSwNCiAgICAgICAgICAgICAgICAgKHN0cmlu
ZyBzKXt3cml0ZWZsbigiaW4gdGhlIHRocmVhZCAlcyIsdGltZXMpO2NvbnQgPSBmYWxzZTt9KTsN
CiAgICB9DQp9DQp2b2lkIG1haW4oc3RyaW5nW10gYXJncyl7DQogICAgDQogICAgYXV0byB0ZCA9
IHNwYXduKCZzaGFyZUF1Z21lbnRlcik7DQogICAgaW50W10gaXRlcmF0aW9uUmFuZ2UgPSBuZXcg
aW50WzI1MDBdOw0KICAgIGZvcmVhY2ggKHBvcywgcmVmICBpOyBwYXJhbGxlbChpdGVyYXRpb25S
YW5nZSkpew0KICAgICAgICB0ZC5zZW5kKDEpOw0KICAgIH0NCiAgICB3cml0ZWxuKHRpbWVzKTsN
CiAgICB0ZC5zZW5kKCIiKTsNCiAgICB3cml0ZWxuKHRpbWVzKTsNCnByaW50cyANCjANCjANCklu
IHRoZSB0aHJlYWQgMjUwMA0KDQpDaGVlcnMsDQpDaGFybGVzLg0K
Jul 22 2011
parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 22 Jul 2011 18:38:15 -0400, McAnany, Charles E  
<mcanance rose-hulman.edu> wrote:

 Hi, all. So I'm getting the classic "concurrency noob" behavior from  
 this code:
     shared int times;
     int[] iterationRange = new int[2500];
     foreach (pos, ref  i; parallel(iterationRange)){
         times++;
     }
     writeln(times);
 }
 Prints random numbers near 1,000.
 Looking at the documentation for std.concurrency, it appears that when  
 dealing with tasks, you have to yieldForce to get them to finish. Is  
 there a method that blocks until taskPool itself is empty?

I think you are misreading something, std.concurrency does not have to do with std.parallelism Note that while compiler inserts memory barriers around operations on shared data, it does not get rid of race issues. That is, times++ is *not* atomic, so you cannot expect it to avoid races. Try: import core.atomic; atomicOp!"+="(times, 1);
 I think the problem is not concurrent modification, the foreach just  
 seems to return too early, as seen here:

 int times;
 void shareAugmenter(){
     bool cont = true;
     while(cont){
         receive( (int i){times++;},
                  (string s){writefln("in the thread %s",times);cont =  
 false;});
     }
 }
 void main(string[] args){
    auto td = spawn(&shareAugmenter);
     int[] iterationRange = new int[2500];
     foreach (pos, ref  i; parallel(iterationRange)){
         td.send(1);
     }
     writeln(times);
     td.send("");
     writeln(times);
 prints
 0
 0
 In the thread 2500

Note that int times is THREAD LOCAL, so essentially you have created two separate copies of times, one in the main thread and one in the sub thread. Change the declaration to: shared int times; -Steve
Jul 25 2011