ANTsR icon indicating copy to clipboard operation
ANTsR copied to clipboard

Parallelizing permutations with `foreach` ?

Open dorianps opened this issue 6 years ago • 3 comments

I am trying to build a parallel routine to run some permutation analysis.

When done on a serial manner, each permutation updates a single variable which keeps count of how many times a voxel exceeds the statistical value in permutations to later establish pvalues. The use of a single central variable decreases the memory footprint. Saving, or loading the result of each permutation would be too heavy (i.e., think 10,000 images loaded in memory).

When parallelizing this, I need each worker to update a single variable. However, this does not seem as easy as it looks. Some people advise to use pointer. Since our antsImages are S4 pointers, I thought that would work, I still cannot get the foreach loop to update the image.

Does anybody have any idea how to resolve this?

Here is some code that I played around with:


library(ANTsR)

img = antsImageRead('/home/dorian/svr-lesymap/1000perms/mask_img.nii.gz') # just a 3D mask of a hemisphere
imgtest = antsImageClone(img)
vector = imageListToMatrix(list(img), img)[1,]

randomvec = sample(1:length(vector), size = 100000)
temp = vector
temp[-(randomvec)] = 0
randomask = makeImage(img, temp)

runs = 100

###########################################

library(doParallel) 
ncores = 15
registerDoParallel(cores=ncores) 

###############################
max(imgtest)
temp =foreach (i=1:100, .combine='c') %dopar% {
  imgtest[randomask] = imgtest[randomask] + 1
}
max(imgtest)

dorianps avatar Nov 05 '18 22:11 dorianps

Still looking for a solution to this. Opened also a thread on Stackoverflow, maybe R experts come up with an idea. https://stackoverflow.com/questions/54613330/update-single-common-variable-in-parallel-foreach-loop

The issue is simple: there is no way to update a common vector/S4/antsImage using foreach in R.

Here is some reproducible code:

library(ANTsR)

# load example image and make a mask

img = antsImageRead(getANTsRData( "r16" ))
mask = getMask(img)


###########################################

library(doParallel) 
ncores = 2
registerDoParallel(cores=ncores) 

###############################

# parallel loop cannot update img S4 object

foreach (i=1:10, .combine='c', .export = c('img','mask'), 
         .packages = c('ITKR', 'ANTsRCore', 'ANTsR') ) %dopar% {

  # max(img) # output: 254
  # print(img@pointer) # output: <pointer: (nil)>
   img[mask] = 0 # output: no change to img
}

# standard for loop works

for (i in 1:10)  {
  # print(img@pointer) output: <pointer: 0x5510610>
  # max(img) # output: 254
   img[mask] = 0 # output: img black
}

dorianps avatar Feb 10 '19 04:02 dorianps

Are you sure the last line of the foreach shouldn't be img? e.g.:

foreach (i=1:10, .combine='c', .export = c('img','mask'), .packages = c('ITKR', 'ANTsRCore', 'ANTsR') ) %dopar% {

       # max(img) # output: 254
       # print(img@pointer) # output: <pointer: (nil)>
       img[mask] = 0 # output: no change to img
       img
     }

Also, to compare to a for loop, you should use %do% rather than %dopar%: sum(img) foreach (i=1:10, .combine='c', .export = c('img','mask'), .packages = c('ITKR', 'ANTsRCore', 'ANTsR') ) %do% {

       # max(img) # output: 254
       # print(img@pointer) # output: <pointer: (nil)>
       img[mask] = 0 # output: no change to img
     }

sum(img)

John

On Sat, Feb 9, 2019 at 6:33 PM dorianps [email protected] wrote:

Still looking for a solution to this. Opened also a thread on Stackoverflow, maybe R experts come up with an idea.

https://stackoverflow.com/questions/54613330/update-single-common-variable-in-parallel-foreach-loop

The issue is simple: there is not way to update a common vector/S4/antsImage using foreach in R.

Here is some reproducible code:

library(ANTsR)

load example image and make a mask

img = antsImageRead(getANTsRData( "r16" )) mask = getMask(img)

###########################################

library(doParallel) ncores = 2 registerDoParallel(cores=ncores)

###############################

parallel loop cannot update img S4 object

foreach (i=1:10, .combine='c', .export = c('img','mask'), .packages = c('ITKR', 'ANTsRCore', 'ANTsR') ) %dopar% {

max(img) # output: 254

print(img@pointer) # output: <pointer: (nil)>

img[mask] = 0 # output: no change to img }

standard for loop works

for (i in 1:10) {

print(img@pointer) output: <pointer: 0x5510610>

max(img) # output: 254

img[mask] = 0 # output: img black }

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/ANTsX/ANTsR/issues/245#issuecomment-462103000, or mute the thread https://github.com/notifications/unsubscribe-auth/ABBnrv8yJrDIeJBvI3mlzTf0TULkaB5Tks5vL6EegaJpZM4YPXXB .

muschellij2 avatar Feb 10 '19 18:02 muschellij2

Well... the problem is not what each foreach worker is returning, they may return NULL for what I care. The problem is that the workers should update the same antsImage which points at <pointer: 0x5510610>, and when the loop is finished I can access the same antsImage to find the results of all "independent" workers. The question is: how to make all workers update some sort of common variable. It can be an antsImage or any other object.

dorianps avatar Feb 11 '19 20:02 dorianps