From: Jan Svitok Date: 2007-03-12T07:37:51+09:00 Subject: Re: Trying to make Array#collect massively parallel with OpenMP On 3/11/07, Daniel Berger wrote: > Hi all, > > Windows XP Home > VC++ 8 (free edition) > > Just for kicks I tried creating a parallel Array#collect method, which > I called Array#acollect (asynch. collect). I added the following C > code to array.c, rebuilt and reinstalled, but it doesn't seem to be > any faster. Could this be an issue with my compiler? Or a Windows > thing? > > static VALUE rb_ary_acollect(VALUE ary){ > long i; > VALUE collect; > > if (!rb_block_given_p()) > return rb_ary_new4(RARRAY(ary)->len, RARRAY(ary)->ptr); > > collect = rb_ary_new2(RARRAY(ary)->len); > > #pragma omp parallel for > for (i = 0; i < RARRAY(ary)->len; i++) > rb_ary_push(collect, rb_yield(RARRAY(ary)->ptr[i])); > > return collect; > } > > rb_define_method(rb_cArray, "acollect", rb_ary_acollect, 0); > > # bench_collect.rb > require "benchmark" > > MAX = 4000 > > array = [] > MAX.times{ |n| > array[n] = 2 * n > } > > # No significant difference (?) > Benchmark.bm(30) do |x| > x.report("Array#collect"){ > MAX.times{ array.collect{ |e| e += 4 } } > } > x.report("Array#acollect"){ > MAX.times{ array.acollect{ |e| e += 4 } } > } > end > > Ideas? > > Thanks, > > Dan Hi, I'm no expert in either ruby internals or openmp. I've just a few ideas for you (though most of them will be obvious probably): 1. http://msdn2.microsoft.com/en-us/library/fw509c3b(VS.80).aspx says you need to add /openmp compiler switch (try using _OPENMP define to see if the compiler recognizes omp pragmas). #include "omp.h" might help as well. 2. in the same page they say you won't see any difference if the whole loop runs under 15 ms on a specific machine (i.e. the thread startup time) 3. try running one loop outside the benchmark to setup the thread pool 4. is the assignment intentional (e += 4)? 5. (just for my curiosity:) are you using 1.8 or 1.9? 6. I've heard that 1.8 interpreter runs in one thred. I suppose your code runs correctly with multiple threads because there should not be any (re)allocations (e.g. it might crash if there was a local var in the block). Right? 7. what machine are you running this code on? (if you send me the binary or patch I might try it on my core2 machine if that helps) 8. I suppose the difference might be bigger if you used more complicated (longer) block (relates to #2) 9. if everything fails, try running pure c loops (without calling ruby functions) with omp optimisation, possibly wrapped into a ruby function to see if omp makes at least difference at c level ok, I've run out of ideas for now... Jano