Parallelism Map and Reduce

Ali Çehreli acehreli at yahoo.com
Tue Dec 11 07:22:49 PST 2012


On 12/11/2012 02:53 AM, Zardoz wrote:

 > auto acelByObjs = map!( (Entity o) {
 > Vector3 r = o.pos[0] - pos[0];
 > return r * (o.mass / pow((r.sq_length + epsilon2), 1.5));
 > } )(objects);
 > newAcel = reduce!("a + b")(acelByObjs);
 >
 > It works very well with the std.algorithm Map and Reduce but when I try
 > to use std.parallelism versions of it, parallel Map give me this
 > compilataion errors :
 >
 > entity.d(63): Error: template instance map!(delegate @system
 > Vector3(Entity o)
 > {
 > Vector3 r = o.pos[0LU].opBinary(this.pos[0LU]);
 > return r.opBinary(o.mass / pow(r.sq_length() + epsilon2,1.5));
 > }
 > ) cannot use local '__lambda3' as parameter to non-global template
 > map(functions...)

That used to work a couple of dmd versions ago. I think it was a bug 
that it worked, so it stopped working after bug fixes.

If I'm not mistaken this is actually related to a compiler 
implementation issue: Lambda's have a single pointer to store the 
context that they have been started in.

When a lambda is a free-standing function (aka "module function" or 
"global function") then there is only the context to deal with. When the 
template is a member function (taskPool.map is) then there is also the 
object that the function is started on.

The single pointer of the lambda is not sufficient to store both without 
big changes in the compiler.

(I may be off with that description above. e.g. there may be two 
pointers when three are actually needed, etc.)

I had to change following chapter after dmd's behavior had changed:

   http://ddili.org/ders/d.en/parallelism.html

--- Quoting ---
import std.parallelism;
// ...
double averageGrade(Student student)
{
     return student.averageGrade;
}
// ...
     auto results = taskPool.map!averageGrade(students, 3);

Note: The free-standing averageGrade() function above is needed due to a 
limitation that involves using local delegates with member function 
templates like TaskPool.map:

   auto results = taskPool.map!(a => a.averageGrade)(students, 3); 
// ← compilation ERROR
----------

As you see above, the solution is to use a function with taskPool.map, 
not a lambda.

Ali



More information about the Digitalmars-d-learn mailing list