Hi,

sorry to be late to the party...

Please let me try to answer some of your questions in one post.

1. The main purpose for the code was to show how many threads could work on 
one shared data-structure and how the introduction of concurrent 
programming can change the algorithms: in this case moving from generations 
of populations to one population being continuously changed by threads.  In 
addition to that I wanted to demo the concept of self-calling agents while 
another agent indicates the current state of the whole system. 

2. The problem with the increasing of the population depending on the 
number of threads for creating new individuals and removing other from the 
population was initially unforeseen.  However, I kept it in the book 
because it indicates that there are new issues for the programmer to 
handle, when concurrent programming is introduced.  In addition to that, I 
personally think that the management of resources like seen in this example 
will become an issues as soon as we are talking about more than -say- 16 
cores.  I think we will need more control than just one thread pool.

3. This examples does not use Refs and thus it has nothing to do with the 
integration of agents into the STM system.  BTW the integration means that 
the STM will take care that any function sent to an agent within a 
transaction will only be sent exactly one, not for every retry of the 
dosync-body.

4. When I wrote the code it usually evolved within some 10-20 seconds.  On 
a dual core machine.  I wouldn't have put code in the book that took 
several minutes on my machines.  So, I wonder why it is so slow on your 
machines.  (Sidenote: I'd expect a reasonably well tunes GA written 
single-threadedly in C to find the solution in a few seconds at max.)

5. The pmap that you introduced when sending the functions to the agents 
would only queue the functions faster, as Jim mentioned in his last post.  
In my understanding that should not really make any difference.  The 
overhead in that piece of code would be small, because it is only created 
once, not in a tight loop or something.  The increase of memory *might* be 
related to garbage collection being too slow.  Did you try to use parallel 
GC?

6. My use of send-off in the grim reaper agent fn is an error.  send-off is 
supposed to be used for potentially blocking functions, e.g. I/O.  Maybe 
this one is the reason for the problems with growing populations?  send-off 
uses a different thread pool which is not of fixed size (IIRC).  I will 
have to try that out, but it will take a few days.

7. The whole example is rather artificial: usually the fitness function 
would be expensive, whereas in this example it is just boils down to some 
cheap comparisons.  Thus, there will probably be many collisions when 
trying to change the population Atom.  This would decrease the amount of 
concurrency that is possible.  You might want to try to apply the general 
GA idea to a more complicated problem which makes the calculation of the 
fitness more expensive.  In that case the reading an writing on the atom 
would become less, compared to the calculation of the fitness, thereby 
reducing the amount of collisions and repetitions of the update function.

After all that has been said, I sincerely hope, that playing with that 
example helped you understand things better. :-)


Kind regards,
Stefan
 

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to