CUDA - memcpy2d - 错误的音高
CUDA - memcpy2d - wrong pitch
我刚刚开始 CUDA 编程,并尝试执行如下所示的代码。这个想法是将二维数组复制到设备,计算所有元素的总和,然后检索总和(我知道这个算法不是并行化的。事实上,它正在做更多的工作,然后是必要的。然而,这只是作为记忆复制的实践)。
#include<stdio.h>
#include<cuda.h>
#include <iostream>
#include <cutil_inline.h>
#define height 50
#define width 50
using namespace std;
// Device code
__global__ void kernel(float* devPtr, int pitch,int* sum)
{
int tempsum = 0;
for (int r = 0; r < height; ++r) {
int* row = (int*)((char*)devPtr + r * pitch);
for (int c = 0; c < width; ++c) {
int element = row[c];
tempsum = tempsum + element;
}
}
*sum = tempsum;
}
//Host Code
int main()
{
int testarray[2][8] = {{4,4,4,4,4,4,4,4},{4,4,4,4,4,4,4,4}};
int* sum =0;
int* sumhost = 0;
sumhost = (int*)malloc(sizeof(int));
cout << *sumhost << endl;
float* devPtr;
size_t pitch;
cudaMallocPitch((void**)&devPtr, &pitch, width * sizeof(int), height);
cudaMemcpy2D(devPtr,pitch,testarray,0,8* sizeof(int),4,cudaMemcpyHostToDevice);
cudaMalloc((void**)&sum, sizeof(int));
kernel<<<1, 4>>>(devPtr, pitch, sum);
cutilCheckMsg("kernel launch failure");
cudaMemcpy(sumhost, sum, sizeof(int), cudaMemcpyDeviceToHost);
cout << *sumhost << endl;
return 0;
}
这段代码编译得很好(在 4.0 sdk 候选版本上)。但是,一旦我尝试执行,我就会得到
0
cpexample.cu(43) : cutilCheckMsg() CUTIL CUDA error : kernel launch failure : invalid pitch argument.
这很不幸,因为我不知道如何解决它;-(。据我所知,音高是内存中的偏移量,以便更快地复制数据。但是,这样的音高仅用于设备内存,而不用于主机内存,不是吗?因此,我的主机内存的间距应该是0,不是吗?
此外,我还想问另外两个问题:
- 如果我声明一个像 int* sumhost 这样的变量(见上文),这个指针指向哪里?首先到主机内存,然后到cudaMalloc到设备内存?
- 在这种情况下,cutilCheckMsg非常方便。我应该知道有类似的调试功能吗?
在代码的这一行中:
cudaMemcpy2D(devPtr,pitch,testarray,0,8* sizeof(int),4,cudaMemcpyHostToDevice);
你是说testarray
的源音高值等于0
,但是当音高公式T* elem = (T*)((char*)base_address + row * pitch) + column
时,这怎么可能呢? 如果我们在该公式中用 0
的值代替音高,那么在查找某个二维 (x,y) 有序对偏移量的地址时,我们将无法获得正确的值。要考虑的一件事是音高值的规则是 pitch = width + padding
. 在主机上,填充通常等于 0
,但宽度不0
,除非数组中没有任何内容。 在硬件端可能有额外的填充,这就是为什么间距的值可能不等于数组的声明宽度。 因此,您可以根据填充值得出结论,pitch >= width
。 因此,即使在主机端,源音高的值也应至少为每行的大小(以字节为单位),这意味着在testarray
的情况下,它应该是8*sizeof(int)
。 最后,主机中 2D 数组的高度也只有 2
行,而不是 4
.
作为有关分配的指针会发生什么情况的问题的答案,如果使用 malloc()
分配指针,则会为指针提供一个驻留在主机内存中的地址值。 因此,您可以在主机端取消引用它,但不能在设备端取消引用。 另一方面,分配了cudaMalloc()
的指针被赋予指向驻留在设备上的内存的指针。 因此,如果在主机上取消引用它,它不会指向主机上分配的内存,并且会出现不可预知的结果。 不过,将此指针地址传递给设备上的内核是可以的,因为当它在设备端取消引用时,它指向设备本地可访问的内存。 总体而言,CUDA 运行时将这两个内存位置分开,提供内存复制函数,这些功能将在设备和主机之间来回复制,并根据所需的方向(主机到设备或设备到主机)使用这些指针中的地址值作为复制的源和/或目标。 现在,如果您采用相同的int*
,并首先使用malloc()
分配它,然后(在希望调用指针free()
之后)使用cudaMalloc()
,则指针将首先具有指向主机内存的地址,然后是设备内存。 您必须跟踪其状态,以避免取消引用设备或主机上的地址而导致不可预知的结果,具体取决于该地址是在主机代码中还是在设备代码中取消引用的。
- 警告处理为错误这里有什么问题
- "error: no matching function for call to"构造函数错误
- boost::进程间消息队列引发错误
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- QT在错误的班级中寻找空位
- vector.resize()中的分配错误
- 代码在main()中运行,但在函数中出现错误
- 释放错误后堆使用
- (C++)分析树以计算返回错误值的简单算术表达式
- Project Euler问题4的错误解决方案
- 我的字符计数代码计算错误.为什么
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 尝试导入pybind-opencv模块时出现libgtk错误
- CMake项目Boost库错误:Boost/config/compiler/gcc.hpp:165:10:致命错误:cs
- 在某些循环内使用vector.push_back时出现分段错误
- MSVC多行宏编译器错误
- 静态数据成员的问题-修复链接错误会导致编译器错误
- 为什么在运行时没有向我们提供有关分段错误的更多信息?
- CUDA - memcpy2d - 错误的音高