pyCuda,发送多个单变量参数的问题
pyCuda, issues sending multiple single variable arguments
我这里有一个 pycuda 程序,它从命令行读取图像并保存颜色反转的版本:
import pycuda.autoinit
import pycuda.driver as device
from pycuda.compiler import SourceModule as cpp
import numpy as np
import sys
import cv2
modify_image = cpp("""
__global__ void modify_image(int pixelcount, unsigned char* inputimage, unsigned char* outputimage)
{
int id = threadIdx.x + blockIdx.x * blockDim.x;
if (id >= pixelcount)
return;
outputimage[id] = 255 - inputimage[id];
}
""").get_function("modify_image")
print("Loading image")
image = cv2.imread(sys.argv[1], cv2.IMREAD_UNCHANGED).astype(np.uint8)
print("Processing image")
pixels = image.shape[0] * image.shape[1]
newchannels = []
for channel in cv2.split(image):
output = np.zeros_like(channel)
modify_image(
device.In(np.int32(pixels)),
device.In(channel),
device.Out(output),
block=(1024,1,1), grid=(pixels // 1024 + 1, 1))
newchannels.append(output)
finalimage = cv2.merge(newchannels)
print("Saving image")
cv2.imwrite("processed.png", finalimage)
print("Done")
即使在较大的图像上,它也能完美运行。然而,在尝试扩展程序的功能时,我遇到了一个非常奇怪的问题,即向内核添加第二个变量参数会导致程序完全失败,只是保存一个全黑的图像。以下代码不起作用;
import pycuda.autoinit
import pycuda.driver as device
from pycuda.compiler import SourceModule as cpp
import numpy as np
import sys
import cv2
modify_image = cpp("""
__global__ void modify_image(int pixelcount, int width, unsigned char* inputimage, unsigned char* outputimage)
{
int id = threadIdx.x + blockIdx.x * blockDim.x;
if (id >= pixelcount)
return;
outputimage[id] = 255 - inputimage[id];
}
""").get_function("modify_image")
print("Loading image")
image = cv2.imread(sys.argv[1], cv2.IMREAD_UNCHANGED).astype(np.uint8)
print("Processing image")
pixels = image.shape[0] * image.shape[1]
newchannels = []
for channel in cv2.split(image):
output = np.zeros_like(channel)
modify_image(
device.In(np.int32(pixels)),
device.In(np.int32(image.shape[0])),
device.In(channel),
device.Out(output),
block=(1024,1,1), grid=(pixels // 1024 + 1, 1))
newchannels.append(output)
finalimage = cv2.merge(newchannels)
print("Saving image")
cv2.imwrite("processed.png", finalimage)
print("Done")
唯一的区别在于两条线,内核 header 和它的调用。内核本身的实际代码没有改变,但是这个小的添加完全破坏了程序。编译器和解释器都不会抛出任何错误。我不知道如何开始调试它,并且完全困惑。
好的,所以通过将可变参数更改为内核中的指针,它修复了代码,我不确定如何或为什么。这里是修改后的内核版本;
__global__ void modify_image(int* pixelcount, int* width, unsigned char* inputimage, unsigned char* outputimage)
{
int id = threadIdx.x + blockIdx.x * blockDim.x;
if (id >= *pixelcount)
return;
outputimage[id] = 255 - inputimage[id];
}
代码的其余部分没有改变。如果有人想解释为什么这是一个成功的修复,我将不胜感激。
device.In
和亲戚设计用于支持 Python 缓冲协议的对象(如 numpy 数组)。问题的根源是使用它们来传输非缓冲区对象。
只需将具有正确 numpy dtype 的标量直接传递给内核调用即可。不要使用 device.In
。这在原始案例中起作用的事实完全是意外
我这里有一个 pycuda 程序,它从命令行读取图像并保存颜色反转的版本:
import pycuda.autoinit
import pycuda.driver as device
from pycuda.compiler import SourceModule as cpp
import numpy as np
import sys
import cv2
modify_image = cpp("""
__global__ void modify_image(int pixelcount, unsigned char* inputimage, unsigned char* outputimage)
{
int id = threadIdx.x + blockIdx.x * blockDim.x;
if (id >= pixelcount)
return;
outputimage[id] = 255 - inputimage[id];
}
""").get_function("modify_image")
print("Loading image")
image = cv2.imread(sys.argv[1], cv2.IMREAD_UNCHANGED).astype(np.uint8)
print("Processing image")
pixels = image.shape[0] * image.shape[1]
newchannels = []
for channel in cv2.split(image):
output = np.zeros_like(channel)
modify_image(
device.In(np.int32(pixels)),
device.In(channel),
device.Out(output),
block=(1024,1,1), grid=(pixels // 1024 + 1, 1))
newchannels.append(output)
finalimage = cv2.merge(newchannels)
print("Saving image")
cv2.imwrite("processed.png", finalimage)
print("Done")
即使在较大的图像上,它也能完美运行。然而,在尝试扩展程序的功能时,我遇到了一个非常奇怪的问题,即向内核添加第二个变量参数会导致程序完全失败,只是保存一个全黑的图像。以下代码不起作用;
import pycuda.autoinit
import pycuda.driver as device
from pycuda.compiler import SourceModule as cpp
import numpy as np
import sys
import cv2
modify_image = cpp("""
__global__ void modify_image(int pixelcount, int width, unsigned char* inputimage, unsigned char* outputimage)
{
int id = threadIdx.x + blockIdx.x * blockDim.x;
if (id >= pixelcount)
return;
outputimage[id] = 255 - inputimage[id];
}
""").get_function("modify_image")
print("Loading image")
image = cv2.imread(sys.argv[1], cv2.IMREAD_UNCHANGED).astype(np.uint8)
print("Processing image")
pixels = image.shape[0] * image.shape[1]
newchannels = []
for channel in cv2.split(image):
output = np.zeros_like(channel)
modify_image(
device.In(np.int32(pixels)),
device.In(np.int32(image.shape[0])),
device.In(channel),
device.Out(output),
block=(1024,1,1), grid=(pixels // 1024 + 1, 1))
newchannels.append(output)
finalimage = cv2.merge(newchannels)
print("Saving image")
cv2.imwrite("processed.png", finalimage)
print("Done")
唯一的区别在于两条线,内核 header 和它的调用。内核本身的实际代码没有改变,但是这个小的添加完全破坏了程序。编译器和解释器都不会抛出任何错误。我不知道如何开始调试它,并且完全困惑。
好的,所以通过将可变参数更改为内核中的指针,它修复了代码,我不确定如何或为什么。这里是修改后的内核版本;
__global__ void modify_image(int* pixelcount, int* width, unsigned char* inputimage, unsigned char* outputimage)
{
int id = threadIdx.x + blockIdx.x * blockDim.x;
if (id >= *pixelcount)
return;
outputimage[id] = 255 - inputimage[id];
}
代码的其余部分没有改变。如果有人想解释为什么这是一个成功的修复,我将不胜感激。
device.In
和亲戚设计用于支持 Python 缓冲协议的对象(如 numpy 数组)。问题的根源是使用它们来传输非缓冲区对象。
只需将具有正确 numpy dtype 的标量直接传递给内核调用即可。不要使用 device.In
。这在原始案例中起作用的事实完全是意外