- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我是 PyCUDA 的新手,正在浏览 PyCUDA 网站上的一些示例。我正在尝试弄清楚某些代码行背后的逻辑,如果有人解释了它背后的想法,我将不胜感激。
以下代码片段来自 PyCUDA 网站。函数定义里面,没看懂
int idx = threadIdx.x + threadIdx.y*4;
如何使用上面的行来计算数组的索引。为什么threadIdx.x和threadIdx.y加在一起,为什么threadIdx.y乘以4。
对于 GPU 的函数调用,为什么 block 定义为 5,5,1。因为它是一个 5x5 元素的数组,所以根据我的理解, block 大小应该是 5,5 而不是 5,5,1。
import pycuda.driver as cuda
import pycuda.autoinit
from pycuda.compiler import SourceModule
import numpy
a = numpy.random.randn(5,5)
a = a.astype(numpy.float32)
a_gpu = cuda.mem_alloc(a.nbytes)
cuda.memcpy_htod(a_gpu, a)
mod = SourceModule("""
__global__ void doubleMatrix(float *a)
{
int idx = threadIdx.x + threadIdx.y*4;
a[idx] *= 2;
}
""")
func = mod.get_function("doubleMatrix")
func(a_gpu, block=(5,5,1))
a_doubled = numpy.empty_like(a)
cuda.memcpy_dtoh(a_doubled, a_gpu)
print ("ORIGINAL MATRIX")
print a
print ("DOUBLED MATRIX AFTER PyCUDA EXECUTION")
print a_doubled
最佳答案
您发布的示例似乎来自(或抄袭)一本名为“Python Parallel Programming Cookbook”的书,直到五分钟前我才听说过这本书。老实说,如果我是那本书的作者,我会为包含这样一个骇人听闻的错误示例而感到羞愧。
这是对您发布的内容及其输出的一个小修改:
import pycuda.driver as cuda
import pycuda.autoinit
from pycuda.compiler import SourceModule
import numpy
a = numpy.random.randn(5,5)
a = a.astype(numpy.float32)
a_gpu = cuda.mem_alloc(a.nbytes)
cuda.memcpy_htod(a_gpu, a)
mod = SourceModule("""
__global__ void doubleMatrix(float *a)
{
int idx = threadIdx.x + threadIdx.y*4;
a[idx] *= 2.f;
}
""")
func = mod.get_function("doubleMatrix")
func(a_gpu, block=(5,5,1))
a_doubled = numpy.empty_like(a)
cuda.memcpy_dtoh(a_doubled, a_gpu)
print a_doubled - 2.0*a
[警告:Python 2 语法]
In [2]: %run matdouble.py
[[ 0. 0. 0. 0. 0. ]
[ 0. 0. 0. 0. 0. ]
[ 0. 0. 0. 0. 0. ]
[ 0. 0. 0. 0. 0. ]
[ 0. -0.62060976 0.49836278 -1.60820103 1.71903515]]
即代码没有按预期工作,这可能是您感到困惑的根源。
在 this very recent answer 中描述了寻址存储在线性内存中的多维数组(如 numpy 数组)的正确方法。 .任何明智的程序员都会像这样在您的示例中编写内核:
__global__ void doubleMatrix(float *a, int lda)
{
int idx = threadIdx.x + threadIdx.y * lda;
a[idx] *= 2.f;
}
以便将数组的前导维度作为参数传递给内核(在本例中应为 5,而不是 4)。这样做会得到以下结果:
import pycuda.driver as cuda
import pycuda.autoinit
from pycuda.compiler import SourceModule
import numpy
a = numpy.random.randn(5,5)
a = a.astype(numpy.float32)
a_gpu = cuda.mem_alloc(a.nbytes)
cuda.memcpy_htod(a_gpu, a)
mod = SourceModule("""
__global__ void doubleMatrix(float *a, int lda)
{
int idx = threadIdx.x + threadIdx.y * lda;
a[idx] *= 2.f;
}
""")
func = mod.get_function("doubleMatrix")
lda = numpy.int32(a.shape[-1])
func(a_gpu, lda, block=(5,5,1))
a_doubled = numpy.empty_like(a)
cuda.memcpy_dtoh(a_doubled, a_gpu)
print a_doubled - 2.0*a
产生预期结果:
In [3]: %run matdouble.py
[[ 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0.]]
For the function call to the GPU why is the block defined as 5,5,1. Since it is an array of 5x5 elements so in my understanding the block size should be 5,5 instead of 5,5,1.
在 CUDA 中,所有 block 都隐式具有三个维度。 (5,5) 的 block 大小与 (5,5,1) 的 block 大小相同。最后一个维度可以忽略,因为它是一个维度(即 block 中的所有线程都有 threadIdx.z = 1
)。您不应该陷入的陷阱是将 CUDA block 或网格的维度与输入数组的维度混为一谈。有时让它们相同很方便,但同样没有必要甚至不建议这样做。对于此示例(假设行主要存储顺序),以 BLAS 样式正确编写的内核可能如下所示:
__global__ void doubleMatrix(float *a, int m, int n, int lda)
{
int col = threadIdx.x + blockIdx.x * blockDim.x;
int row = threadIdx.y + blockDim.y * blockDim.y;
for(; row < m; row += blockDim.y * gridDim.y) {
for(; col < n; col += blockDim.x * gridDim.x) {
int idx = col + row * lda;
a[idx] *= 2.f;
}
}
}
[注:在浏览器中编写,未经编译或测试]
这里 任何 合法的 block 和网格维度将正确处理任何大小的输入数组元素总数将适合带符号的 32 位整数。如果你运行太多线程,有些线程什么都不做。如果运行的线程太少,一些线程将处理多个数组元素。如果您运行一个与输入数组具有相同维度的网格,每个线程将只处理一个输入,正如您正在研究的示例中的意图。如果您想阅读有关如何选择最合适的 block 和网格大小的信息,我建议您开始 here .
关于python - PyCUDA 核函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43701306/
我创建了一个形状为 (64, 128) 的 float32 numpy 数组,我想将它发送到 GPU。我怎么做?我的内核函数应该接受哪些参数? float** myArray? 我试过直接将数组原样发
示例代码: import pycuda.autoinit import pycuda.driver as drv import numpy from pycuda.compiler import So
我正在尝试编译一些源代码以使用我的 GPU。我为此使用pycuda。当我编译源代码时,我收到一些来自 Python 的错误: C:\Users\Dmitriy\wcm>python ws_gpu.py
我正在尝试在 PyCUDA 中初始化 2D 表面并用 NumPy 2D 数组中的值填充它。据我所知,这个想法是 打开drv.ArrayDescriptor, 使用这个描述符创建drv.Array, 使
我想在 flask 服务器上运行 pyCUDA 代码。该文件直接使用python3正确运行,但使用flask调用相应函数时失败。 相关代码如下: cudaFlask.py: import pycuda
我对 cuda 有一个奇怪的问题, 在下面的片段中, #include #define OUTPUT_SIZE 26 typedef $PRECISION REAL; extern
我在这里有一个 pycuda 程序,它从命令行读取图像并用反转的颜色保存一个版本: import pycuda.autoinit import pycuda.driver as device from
如何让 PyCuda 提取字符串数组而不是一个字符字符串?如果取消注释 C 代码中的该行,您将看到它迭代每个字符而不是每个字符串。 现在我只是想计算每个字符串的长度,但最终会将其变成一个词频计数器
我正在尝试在 Pycuda 代码中实现一个结构,但出现越界错误。我尝试遵循 this教程,但我无法让它适用于我的情况。 该问题很可能是由于指针使用不当造成的,例如该教程表明必须分配指针 memsize
我在安装了 python 2.7(32 位)和安装了 cuda 7.5 whl 的 pycuda 的 Windows 机器上。我在运行示例程序来测试 pycuda 时出错。 Traceback (mo
我这里有一个 pycuda 程序,它从命令行读取图像并保存颜色反转的版本: import pycuda.autoinit import pycuda.driver as device from pyc
足够简单 start=cuda.Event() func(args,block=blockdims) cuda.memcpy_dtoh(d,h) end=cuda.Event() dur=start.
PyCUDA,尽管有其所有缺点,通常都会提供非常好的示例/可从 wiki 下载。但我在示例或文档(或粗略的谷歌搜索)中找不到任何内容来演示 PyCUDA 将工作负载动态分配到多个设备的方法。 有人可以
我正在使用 pycuda 制作相对论光线追踪器。基本上,对于大型 2D 数组中的每个“像素”,我们必须使用 Runge Kutta 求解 6 个 ODE 系统。由于每个集成都独立于其余集成,因此应该非
我是 PyCUDA 的新手,正在浏览 PyCUDA 网站上的一些示例。我正在尝试弄清楚某些代码行背后的逻辑,如果有人解释了它背后的想法,我将不胜感激。 以下代码片段来自 PyCUDA 网站。函数定义里
应该足够简单;我确实想将一个 int 发送到 SourceModule 内核声明,其中 C 函数 __global__......(int value,.....) 随着值的声明和调用... valu
in desaturate_image redarray_gpu = cuda.mem_alloc(self.redarray.nbytes) pycuda._driver.LogicErro
在简单的 CUDA 程序中,我们可以通过包含 cuPrintf.h 来按线程打印消息,但在 PyCUDA 中执行此操作在任何地方都没有解释。如何在 PyCUDA 中做到这一点? 最佳答案 在 Comp
我正在使用 pyCUDA 进行 CUDA 编程。我需要在内核函数中使用随机数。 CURAND 库在其中不起作用(pyCUDA)。由于GPU有很多工作要做,在CPU内部生成随机数然后将它们传输到GPU是
我正在尝试将二维复数数组传递到 PyCUDA 内核中,但得到了意想不到的结果。 这是我的测试代码: import numpy as np import pycuda.driver as cuda im
我是一名优秀的程序员,十分优秀!