1

背景: ある点から 3D グリッド内の各セルまでの距離を計算し、この距離に関数を適用する必要があります。複数のポイントに対してこれを行う必要があり、すべてのポイントの各セルに関数の値を追加します。(x,y,z) にある点に対して次のコードを使用してこれを行うことができます。

x <- c(1,2,3,4,5)
y <- x
z <- x
radius <- c(0.4,0.5,0.6,0.7,0.8)
numsphere <- length(x)
radius_buffer <- 0.2

xvox <- seq((min(x)-1),(max(x)+2),0.5)
yvox <- xvox
zvox <- xvox

probability_array <<- array(0,dim=c(length(xvox),length(yvox),length(zvox)))

for (j in 1:length(yvox)){ # for every y element
  for (i in 1:length(xvox)){ # for every x element
    for (k in length(zvox):1){ # for every z element
      for (n in 1:numsphere){ # for the total number of points
        dist_sd <- ((xvox[i]-x[n])^2+(yvox[j]-y[n])^2+(zvox[k]-z[n])^2)^0.5
        probability_array[i,j,k] <- probability_array[i,j,k] + 
                                    round(exp(-1*(dist_sd-radius[n])^2/(2*radius_buffer^2)),3)
          }
        }
      }
    }

出力は配列で、プロットされた結果は次のようになります。

probability_array <- probability_array/max(probability_array)
contour3d(probability_array,level=c(0.2,0.8,0.9),x=xvox,y=yvox,z=zvox,color = c("aquamarine","gold","darkorange"),alpha = c(0.1,0.2,0.5),add=T)

出力グラフィック

理想的だと思われるため、これを並列化しようとしましたが、機能させることができません。私はもう試した:

cl<-makeCluster(detectCores(),type="SOCK")
registerDoSNOW(cl)

for (j in 1:length(yvox)){
  for (i in 1:length(xvox)){
    for(k in length(zvox):1){
      probability_array[i,j,k] <- foreach(n=1:numsphere, .combine='+') %dopar% {
        dist_sd <- ((xvox[i]-x[n])^2+(yvox[j]-y[n])^2+(zvox[k]-z[n])^2)^0.5
        round(exp(-1*(dist_sd-radius[n])^2/(2*radius_buffer^2)),3)
      }
    }
  }
}

そして次のようなもの:

r <- foreach(j=1:length(yvox)) %:% foreach(i=1:length(xvox)) %:% foreach(k=length(zvox):1) %:% foreach(n=1:numsphere, .combine='+') %do% {

        dist_sd <- ((xvox[i]-x[n])^2+(yvox[j]-y[n])^2+(zvox[k]-z[n])^2)^0.5
        probability_array[i,j,k] <- probability_array[i,j,k] + round(exp(-1*(dist_sd-radius[n])^2/(2*radius_buffer^2)),3)
        probability_array[i,j,k]

}

しかし、私は何か重要なものを見逃しています。どんな助けでも大歓迎です。乾杯

4

1 に答える 1

4

計算を並列化する場合、オーバーヘッドが発生するため、小さい計算よりも大きな計算を並列で実行することをお勧めします。つまり、内側のループではなく、外側のループです。

ただし、この場合、計算を並列化する必要はありません。ベクトル化するだけで済みます。

# 3-dimensional analogue of row() and col()
dim3 <- function( a, i ) { 
  stopifnot( length(dim(a)) == 3 )
  r <- a
  if( i == 1 ) { r[] <- rep(1:dim(a)[1], dim(a)[2] * dim(a)[3]) }
  if( i == 2 ) { r[] <- rep(1:dim(a)[2], each = dim(a)[1], times = dim(a)[3]) }
  if( i == 3 ) { r[] <- rep(1:dim(a)[3], each = dim(a)[1] * dim(a)[2]) }
  r
}

probability_array <- array(0,dim=c(length(xvox),length(yvox),length(zvox)))
i <- dim3(probability_array,1)
j <- dim3(probability_array,2)
k <- dim3(probability_array,3)
for (n in 1:numsphere){
  dist_sd <- sqrt(
    (xvox[i]-x[n])^2 + (yvox[j]-y[n])^2 + (zvox[k]-z[n])^2
  )
  probability_array <- probability_array + 
    # Rounding intermediate results looks suspicious
    round(exp(-1*(dist_sd-radius[n])^2/(2*radius_buffer^2)),3)
}
于 2013-08-21T08:22:24.010 に答える