Appreciate the attention and the help, Timothy. Let me answer. * the global time ref might indeed be incorrect. I just half- understood how to make a global incrementing counter and implemented it in a way that seemed to work. I'll look into the correct way of doing that. Right now, when I simulate, inc-year is called 8 times every 90 seconds, as calculating one year takes each cpu about 90 seconds.
Randomization is going to be a longer discussion, so hold on =). Why I use randomization at all: * I wanted to avoid that 8 cpu's were all starting with trying to do a birth event at position 0, as that seemed to me would cause an unneccesary amount of collisions between different cpu's. So I shuffle the order of the positions to check once per year per cpu. * I also wanted to avoid a bias in the number of living people reported. If birth always happened before death, then report (coming after 'birth' and 'death') would show a lower number of living hosts than that were actually on average alive. Therefore I shuffle the order of the events once per year per cpu. Why don't I use full randomization (dotimes [i (* popsize num_events)] (random event, random location): * I need to keep track of time somehow, and thus that I need to know the number of events that happened per year. The doseq gives me that. * Normally, if you do a 1000x (random event, random location) type scheme, only ~666 positions get visited. 333 people therefore escape their yearly death-chance check. Next year, that is 111 people, next year that is 33 people.. it basically makes some people live longer than they are supposed to, and then the model is no longer following the death-chance formula that came from the literature, but a variant on it. Why don't I separate the population into 8 groups, rather than in the weird-for-humans separation of 8 years happening simultaneously. * I couldn't think of a bias in what would go wrong if I calculated 8 years simultaneously. As long as I don't need information of what happened when within one of these 8-year bouts, I think I am fine. It seems to be equivalent to a single-processor simulation where my doseq [birth death infect ..etc] is just 8 times bigger, and somewhat randomized. * I think (but I am not sure) that an 8 years can handle it better if someone else decides to log onto this computer I'm running on and use up 2-3 processors. * I enjoyed doing something in a way that screwed with my mind. see it as brain-training ;). Why don't I generate a to-do list for every position and let god sort the mess out ;). * I saw that there were a number of options in how to change the single-threaded model I had to a multithreaded one (see http://groups.google.com/group/clojure/browse_thread/thread/a4395b433b1d4532?q=#9206300ff652fe3e ), and the one I am using now happened to be an easy conversion. * This variant seems to be light on the number of threads. My population size is now a 1000 hosts, but I will probably run sims with 10,000 and 100,000 hosts as well. Not knowing that much about how threads work inside a machine, I worried about sending off a 100,000 agents. Why do I :gather the way I do. * Rich also commented on this one. I'm not sure how to do it better. I'll look into it. On Dec 23, 12:44 pm, Timothy Pratley <timothyprat...@gmail.com> wrote: > Hi Boris, > > Just digging a little deeper into your code, and I'm convinced that > the global time ref is the problem: > > ; you currently have: > (defn do-year "Calculate one year" [_] > (send (agent nil) inc-year) ; this seems to be totally wrong > ; global year gets updated to year+1 > ; you start 8 agents at once, so year gets +8 if the inc can go > through before any dereffing > ; if dereffing occurs then with 8 agents dereffing i can imagine a > transaction timeout occuring > ; most likely scenario all agents operate on year 8, but subject to > race conditions. > (doseq [a (shuffle-java [birth death infect infect evolve evolve > evolve evolve evolve]) > i (shuffle-java (range popsize))] > (a i))) > > Also if I may comment... > What is the purpose of shuffling the functions and the order of world > location visits? It has not introduced any real randomization... what > it does is shuffle the order of functions once, then applies all of > the functions in that particular order to every world location. > (visiting them in a shuffled order, but they all get visited and have > the functions applied in the same order). The only randomization is > that evolve may happen before birth before death, but that will happen > in the same order for all locations for that year. > I think you actually want to do something different like either: > 1) death checks at every location, birth checks at every location, > infection checks, evolve checks > 2) randomly apply events > 3) a combination: standard age death check for every living entity, > total pop birth rate check, random infections/evolutions based on > probabilities applied only as needed > > From what I've seen what you are modeling is a simulation where every > year events occur and modify locations. This sounds chronologically > driven so you wouldn't want separate threads doing separate years as > there is a dependency (year 1 must occur before year 2, before year > 3)... So a more sensible way to split up the work would be to process > 1/8th of the locations per thread (for your 8 cpus). > > But if you wanted to use agents to model the problem instead of as a > threading mechanism, you could treat every location as an agent, then > you can simply shoot off modifications for an entire year and let god > sort the mess out. If performance is your goal then splitting the work > explicitly has the least overhead due to context switching. In the > performance case you'd also want to limit contention as much as > possible by eg: where multiple threads use gathered living, instead > pass the living gathering as an input so that it doesn't need to be > calculated multiple times (which in turn is causing derefs) > > Regards, > Tim. --~--~---------~--~----~------------~-------~--~----~ 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 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 -~----------~----~----~----~------~----~------~--~---