Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python pycuda中的加号相等(+;=)运算符_Python_Parallel Processing_Cuda_Gpu_Pycuda - Fatal编程技术网

Python pycuda中的加号相等(+;=)运算符

Python pycuda中的加号相等(+;=)运算符,python,parallel-processing,cuda,gpu,pycuda,Python,Parallel Processing,Cuda,Gpu,Pycuda,我想在pycuda中实现卷积的一种变体 为了简单起见,我将显示插值的矩形内核。 标准卷积可应用如下: import pycuda.autoinit import pycuda.driver as drv import numpy as np from pycuda.compiler import SourceModule mod = SourceModule(""" #include <stdio.h> __global__ void func(flo

我想在pycuda中实现卷积的一种变体

为了简单起见,我将显示插值的矩形内核。 标准卷积可应用如下:

import pycuda.autoinit
import pycuda.driver as drv
import numpy as np
from pycuda.compiler import SourceModule

mod = SourceModule("""
#include <stdio.h>
__global__ void func(float *dest, float *a)
{
  const int img_size = 64;
  const int kernel_size = 3;
  const int kernel_size_half = kernel_size/2;
  const int tx = blockIdx.x * blockDim.x + threadIdx.x;
  const int ty = blockIdx.y * blockDim.y + threadIdx.y;
  int tx_kernel;

  tx_kernel = tx - kernel_size_half;
  for (int idx=-kernel_size_half; idx <= kernel_size_half; idx++) 
  {
      tx_kernel = tx + idx ;
      if ((tx_kernel < 0) || (tx_kernel > img_size-1))
        continue;
      dest[ty * img_size + tx] +=  a[ty * img_size + tx_kernel] / ((float) kernel_size);
  }
}
""")
致:

然而,第一种方法可以很好地工作,但第二种方法不行,因为它无法更新邻居。 有办法绕过它吗

注: 我简化了问题,把重点放在我需要的东西上, 一般的问题是对每个像素使用不同的卷积核,而不是像我在问题中所问的那样使用相同的卷积核

要更改行,请执行以下操作:

dest[ty * img_size + tx] +=  a[ty * img_size + tx_kernel] / ((float) kernel_size);
致:

然而,第一种方法可以很好地工作,但第二种方法不行,因为它无法更新邻居。有办法绕过它吗

从性能角度来看,首选第一种方法。但是,如果您希望“更新邻居”,则应该可以将第二个操作重铸为:

atomicAdd(&(dest[ty * img_size + tx_kernel]), a[ty * img_size + tx] / ((float) kernel_size));

“与计算当前位置wrt邻居不同,我想做相反的事情”这通常是一个更困难的方法,因为现在您有可能同时多个线程更新同一位置。这可能需要原子或其他一些方法来进行分类,这通常会导致执行较慢的实现。尽管如此,如果出于某种原因您希望这样做,我会首先使用原子更新邻居,而不是:
dest[ty*img\u size+tx\u kernel]+=a[ty*img\u size+tx]/((float)kernel\u size)这样做:
atomicAdd(&(dest[ty*img\u size+tx\u kernel]),一个[ty*img\u size+tx]/((float)kernel\u size))
dest[ty * img_size + tx] +=  a[ty * img_size + tx_kernel] / ((float) kernel_size);
dest[ty * img_size + tx_kernel] +=  a[ty * img_size + tx] / ((float) kernel_size);
atomicAdd(&(dest[ty * img_size + tx_kernel]), a[ty * img_size + tx] / ((float) kernel_size));