Python pycuda中的加号相等(+;=)运算符
我想在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
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));