On 12/13/2010 09:45 PM, Heywood Floyd wrote:
Good Evening from Berlin!


Have been reading the chapter about concurrency by Andrei. Nice.

I have some questions, of varying quality, I'm sure.


Let's say that we have some sort of structure of rather complex data. To give 
us something concrete to talk about, let's say this data is a tree of nodes 
representing 3-dimensional objects. It could look something like this: (Not 
complete example, just to give an idea.)

// ...
class Cube : Node{
    float x, y, z, size, mass, elasticity;
    // ...
}
// ...
tree.add(new Cube("cube1"));
tree["cube1"].add(new Cube("cube2"));

Let's further say that this structure of data will be subjected to two 
different activities: 1) We will change properties of some nodes according to 
some complex lengthy calculations, which may even entail changing the position 
of nodes in the tree, and 2) we will traverse the tree in a recursive manner 
and read the properties in order to render a representation of these nodes to 
screen.

These two activities will then be repeated many times, so, let's say we wish to 
do these two activities in parallel as much as possible!

How do we do that?

 From what I can tell, one way of doing this would be to actually have two data structures, one 
which is the "original" and is used for the calculations, and one which is just a copy of 
the data after each calculation. We could then insert a third activity, which me can call 
"copy", inbetween the two threads. Something like this:

|== Calculate ===| Copy |
                            |    v   |===== Render ====|

Seems to me this would then allow us to interlock these two activites:

..|== Calculate ===| Copy |== Calculate ====|..
..|=== Render  ===|    v   |=== Render ====|..

(Sorry if the ASCII graphics looks skewed.)
So let me just try and set up some kind of rudamentary code for this in 
layman's D:

// import ...
void main()
{
     auto tree = new Node();
     tree.add(new Cube("cube1"));

     auto child = spawn(&renderLoop, thisTid);

     while(true)
     {
         calc(tree);
         auto treeCopy = tree.deepDup();
         receiveOnly!bool();
         send(child, treeCopy);
     }
}

void renderLoop(Tid parent){
{
     send(parent, true);
     while(true)
     {
         Node tree = receiveOnly!Node();
         render(tree);
         send(parent, true);
     }
}


So a couple of thoughts here.

- Is this looking ok? What is the "proper" way of going about this?

- How do we send over a large chunk of complex data to another thread and sort of let 
them assume "ownership" of this data? So that the thread receiving the data 
does not need any locks etc. when working with the data? I suppose we could send over the 
entire treeCopy as immutable (?) but let's for the sake of argument assume that 
renderLoop() needs to be able to _write_ in the copy of the tree structure too!

(- Sidenote: How do we efficiently copy a tree-structure of data several times 
per second? Sounds insane to me?)

Let's further, for the sake of argument, NOT consider that the GPU will do most 
of the rendering and that in effect parallelising in this particular case may 
be marginally beneficial. Let's simply assume we have only one processor here: 
your normal household dual-core CPU, and a VGA-graphics card from the 80s.

For me, in my head, parallelising is very much about designing a flow of data through different processes, 
and this flow chart will have certain "hot spots" where data must be guarded. You have one process 
doing something and then "transfering over" some data to the next process that continues the 
calculations. (With process I simply mean data processing activity, not a "unix process".)

|---calc A--->O----calc C---->  etc.
|---calc B-----^

O = transfer point

I find it difficult to see how this is done in D. (Of course, I'm not sure this 
"transfer"-idea makes any practical sense.) I understand immutable makes data 
read-only, contagiously, and shared makes data heavily guarded.

But yes, is there any way we can transfer "ownership" (not sure if that is the 
right term) of data from one thread to another? So that we can have two threads working 
on two pieces data, then let them copy it (or not!), and then transfer ownership and have 
a third thread work on the copied data, without barriers or guards or stuff like that 
during the time of actual work?


Kind regards and sorry for a lengthy sporadic post
/Heywood Floyd





I think you should probably use shared. With the guards and all. And then not copying it, just sending the reference.

If the write barriers make this too slow, try selectively casting away shared at heavy working spots, when you know that's the only place using the object at that time. I think that should be safe. (?) :)

Reply via email to