【问题标题】:Iterating through a 2D array in PyCUDA遍历 PyCUDA 中的二维数组
【发布时间】:2017-10-18 20:15:39
【问题描述】:

我正在尝试遍历 PyCUDA 中的二维数组,但最终得到重复的数组值。我最初抛出一个小的随机整数数组,它按预期工作,但是当我向它抛出图像时,我一遍又一遍地看到相同的值。

这是我的代码

img = np.random.randint(20, size = (4,5))
print "Input array"
print img
img_size=img.shape
print img_size

#nbtes determines the number of bytes for the numpy array a
img_gpu = cuda.mem_alloc(img.nbytes)
#Copies the memory from CPU to GPU
cuda.memcpy_htod(img_gpu, img)


mod = SourceModule("""
#include <stdio.h>
__global__ void AHE(int *a, int row, int col)
{
int i = threadIdx.x+ blockIdx.x* blockDim.x;
int j = threadIdx.y+ blockIdx.y* blockDim.y;
if(i==0 && j ==0)
printf("Output array ");
if(i <row && j < col)
{
    printf(" %d",a[j + i*col]);
}
}
""")

col = np.int32(img.shape[-1])
row = np.int32(img.shape[0])
func = mod.get_function("AHE")
func(img_gpu, row, col, block=(32,32,1))
img_ahe = np.empty_like(img)
cuda.memcpy_dtoh(img_ahe, img_gpu)

现在,当我用转换为 numpy 数组的图像替换随机整数数组时,我最终得到了这个

img = cv2.imread('Chest.jpg',0)
img_size=img.shape
print img_size

#nbtes determines the number of bytes for the numpy array a
img_gpu = cuda.mem_alloc(img.nbytes)
#Copies the memory from CPU to GPU
cuda.memcpy_htod(img_gpu, img)

mod = SourceModule("""
#include <stdio.h>
__global__ void AHE(int *a, int row, int col)
{
int i = threadIdx.x+ blockIdx.x* blockDim.x;
int j = threadIdx.y+ blockIdx.y* blockDim.y;
if(i==0 && j ==0)
printf("Output array ");
if(i <row && j < col)
{
    printf(" %d",a[j + i*col]);
}
}
""")
#Gives you the number of columns
col = np.int32(img.shape[-1])
row = np.int32(img.shape[0])
func = mod.get_function("AHE")
func(img_gpu, row, col, block=(32,32,1))
img_ahe = np.empty_like(img)
cuda.memcpy_dtoh(img_ahe, img_gpu)

【问题讨论】:

  • @talonmies 我尝试过使用浮点数和整数,但我最终还是得到了相同的结果
  • 那就发minimal reproducible example吧,不然没办法说是怎么回事
  • @talonmies 我添加了一个示例输入,使我的问题更加清晰易懂
  • 代码对我来说看起来工作正常。与您关于一次又一次重复相同值的陈述相反,我在您的输出中看不到这一点,实际上您的输出在输出矩阵打印输出中显示了输入矩阵中出现的每个元素,按列分组。如果有什么我想说的,现在less 清楚了,因为您的输出表明代码工作正常。对于寻求调试帮助的问题,您应该提供minimal reproducible example。 SO期望使用必须 here这个词。
  • 好的,现在很明显了。请阅读一些 OpenCV documentation。我的第一条评论是 100% 正确的。您的源图像数据未以每像素 32 位有符号整数存储,并且您的内核正试图以错误的格式读取数据。

标签: python cuda pycuda


【解决方案1】:

这里的问题是您正在加载的图像没有存储为有符号整数的像素值。您的示例的这种修改更符合预期:

import pycuda.driver as cuda
from pycuda.compiler import SourceModule
import numpy as np
import cv2 

import pycuda.autoinit

img = cv2.imread('Chest.jpg',0)
img_size=img.shape
print img_size
print img.dtype

#nbtes determines the number of bytes for the numpy array a
img_gpu = cuda.mem_alloc(img.nbytes)
#Copies the memory from CPU to GPU
cuda.memcpy_htod(img_gpu, img)

mod = SourceModule("""
#include <stdio.h>
__global__ void AHE(unsigned char *a, int row, int col)
{
int i = threadIdx.x+ blockIdx.x* blockDim.x;
int j = threadIdx.y+ blockIdx.y* blockDim.y;
if(i==0 && j ==0)
printf("Output array ");
if(i <row && j < col)
{
    int val = int(a[j + i*col]);
    printf(" %d", val);
}
}
""")
#Gives you the number of columns
col = np.int32(img.shape[-1])
row = np.int32(img.shape[0])
func = mod.get_function("AHE")
func(img_gpu, row, col, block=(32,32,1))
img_ahe = np.empty_like(img)
cuda.memcpy_dtoh(img_ahe, img_gpu)

当运行代码时会发出这个:

$ python image.py 
(681, 1024)
uint8
Output array  244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 245 245 245 246 246 246 246 246 246 246 246 246 246 246 244 244 244 244 244 244 244 244 245 245 245 245 245 245 245 245 244 244 245 245 245 246 246 246 

[为简洁起见对输出进行了剪辑]

注意图像的dtype - uint8。您的代码试图将无符号 8 位值流视为整数。从技术上讲,它应该在完整图像上生成运行时错误,因为内核将读取图像的大小,因为它每像素读取 4 个字节而不是 1 个字节。但是,您看不到这一点,因为您只运行一个块,并且您的输入图像大概比您运行的块的 32 x 32 大小至少大四倍。

顺便说一句,PyCUDA 非常擅长管理和执行 CUDA 调用的类型安全,但是您的代码巧妙地破坏了 PyCUDA 可以检测内核调用中的类型不匹配的所有机制。 PyCUDA 包含一个出色的 GPUarray 类。你应该熟悉它。如果你在这里使用了 GPUarray 实例,你会得到类型不匹配的运行时错误,这会在你第一次尝试运行它时提醒你问题的确切来源。

【讨论】:

    猜你喜欢
    • 2016-09-04
    • 1970-01-01
    • 2013-03-14
    • 1970-01-01
    相关资源
    最近更新 更多