For some time, I have had a need for an easy way to make use of all of the cores of a single machine through multiple threads or processes, i.e., not a SIMD/vectorized paradigm. The IDL_IDLBridge
is capable of doing this, but setup and usage is fairly painful. To make it easier, I have created a simple multicore library for IDL.
The simplest example is to create a process to execute an IDL command and then meet up with the main thread, like the mg_process_join_demo
in the examples:
p = mg_process(name='subprocess', output='')
p->execute, 'mg_process_join_demo', /nowait
; main process free to do other stuff at this point
p->join ; main process and subprocess will meet here
Another example uses a pool class to create a pool of processes that work together to perform their part of a larger task. In this example, we will compute x^2 + y^3
for 100 values[1] using a pool with the number of processes corresponding to the number of cores available. We need a function to apply to each element of our x
and y
arrays:
function mg_pool_map_demo, x, y
compile_opt strictarr
return, x^2 + y^3
end
Now, we create a pool with the default number of processes being the number of cores available:
pool = mg_pool()
Create our datasets:
n = 100L
x = findgen(n)
y = 0.5 * findgen(n)
Then just pass our data to MG_Pool::map
and indicate which function to apply to the data:
x_squared = pool->map('mg_pool_map_demo', x, y)
This will block, i.e., it returns control to the main process when finished processing. At this point, the result is computed:
print, x_squared, format='(8(F10.2))'
I have used this library to get fairly good performance on an 8 core laptop doing some image processing operations on a few hundred image files, as shown in the graph below.
This, of course, is not enough work to make this a good idea for performance and is only intended as a fast and simple example of using the library. ??
May 26th, 2015 at 6:43 pm
Hi Michael,
This looks very interesting!
You don’t state this explicitly, but this is for IDL8+, right? I am stuck on IDL7 because of some pesky legacy a[where(sometimes this isn’t true)] type code…
Do you think it would be easy to generalize this to older versions of IDL?
G
May 26th, 2015 at 7:44 pm
I don’t believe it uses any newer features, but I have not tested on any version besides IDL 8.4. I do think there have been some bug fixes on recent versions of the
IDL_IDLBridge
that might affect how useful this library is.Please let me know your experience if you try this on other versions of IDL!
May 27th, 2015 at 10:00 am
A quick glance through mg_pool suggests it uses lists and lambda functions… not sure your blog is where you’d like me to post this but here’s what I get with IDL 7.1 on latest Mac OS:
May 27th, 2015 at 10:09 am
Ah, you’re right, I use other IDL 8+ features, unrelated to the
IDL_IDLBridge
! Those could probably be removed with some work.June 3rd, 2015 at 7:22 pm
Mike,
Would you post the source code for mg_log.pro?
Thanks!
Dick
June 3rd, 2015 at 7:35 pm
Get the source code for any routines I used from my library.
June 10th, 2015 at 11:42 am
@gianguido
If your legacy code has:
giving the wrong answer because
[-1]
now indexes the last element, you can use:which will give you an array of length 0, as it should.
June 24th, 2015 at 1:59 pm
I wrote a similar pool object. It’s always been a nuisance that Exelis hasn’t developed the IDL_IDLBridge object any more or produced a proper pool object, akin to what Python has. Because your object makes some of the same assumptions as mine about how to control the function/procedure (such as inputs/outputs, iteratable variables, etc.). You’d really like a thing that does something like the lambda function but in pool object in terms of swapping in/out the pool functionality.
Very nice!
January 24th, 2017 at 11:53 am
Very cool! I was just about to set down the road of writing something like this myself, but now I don’t have to!
January 25th, 2017 at 4:40 pm
Hope it’s useful! Please let me know if it’s useful for you and I would appreciate any pull requests of updates you make.