Cuda 结构到设备内存和从设备内存的深度复制
我在cuda代码中遇到了一个结构数组的深层拷贝问题,该数组中动态分配了成员变量。我认为这是因为Cuda 结构到设备内存和从设备内存的深度复制,cuda,Cuda,我在cuda代码中遇到了一个结构数组的深层拷贝问题,该数组中动态分配了成员变量。我认为这是因为&deviceHistogram指向主机上的地址,而不是设备上的地址。我试着像中那样制作一个中间指针变量,但没有成功;如何正确复制整个结构数组,以便从makeHistogram函数中修改它 #include <stdlib.h> #include <stdio.h> #include "cuda.h" typedef struct histogramBin { int*
&deviceHistogram
指向主机上的地址,而不是设备上的地址。我试着像中那样制作一个中间指针变量,但没有成功;如何正确复制整个结构数组,以便从makeHistogram
函数中修改它
#include <stdlib.h>
#include <stdio.h>
#include "cuda.h"
typedef struct histogramBin {
int* items;
int count;
} histogramBin;
__host__ __device__ void outputHistogram(histogramBin* histogram, int size) {
for (int i = 0; i < size; i++) {
printf("%d: ", i);
if (!histogram[i].count) {
printf("EMPTY");
} else {
for (int j = 0; j < histogram[i].count; j++) {
printf("%d ", histogram[i].items[j]);
}
}
printf("\n");
}
}
// This function embeds PTX code of CUDA to extract bit field from x.
__device__ uint bfe(uint x, uint start, uint nbits) {
uint bits;
asm("bfe.u32 %0, %1, %2, %3;"
: "=r"(bits)
: "r"(x), "r"(start), "r"(nbits));
return bits;
}
__global__ void makeHistogram(histogramBin** histogram, int* rH, int rSize, int bit) {
for (int r = 0; r < rSize; r++) {
int thisBin = bfe(rH[r], bit, 1);
int position = (*histogram)[thisBin].count; // **** out of memory access here****
(*histogram)[thisBin].items[position] = rH[r];
(*histogram)[thisBin].count++;
}
}
void histogramDriver(histogramBin* histogram, int* rH, int rSize, int bit) {
int n = 8;
int* deviceRH;
histogramBin* deviceHistogram;
cudaMalloc((void**)&deviceRH, rSize * sizeof(int));
cudaMemcpy(deviceRH, rH, rSize * sizeof(int), cudaMemcpyHostToDevice);
cudaMalloc((void**)&deviceHistogram, n * sizeof(histogramBin));
cudaMemcpy(deviceHistogram, histogram, n * sizeof(histogramBin), cudaMemcpyHostToDevice);
int* tempData[n];
for (int i = 0; i < n; i++) {
cudaMalloc(&(tempData[i]), rSize * sizeof(int));
}
for (int i = 0; i < n; i++) {
cudaMemcpy(&(deviceHistogram[i].items), &(tempData[i]), sizeof(int*), cudaMemcpyHostToDevice);
}
for (int i = 0; i < n; i++) {
cudaMemcpy(tempData[i], histogram[i].items, rSize * sizeof(int), cudaMemcpyHostToDevice);
}
makeHistogram<<<1, 1>>>(&deviceHistogram, deviceRH, rSize, bit);
cudaDeviceSynchronize();
}
int main(){
int rSize = 5;
int rH[rSize] = {1, 2, 3, 4, 5};
histogramBin * histogram = (histogramBin*)malloc(sizeof(histogramBin) * 8);
for(int i = 0; i < 8; i++){
histogram[i].items = (int*)calloc(sizeof(int), rSize);
histogram[i].count = 0;
}
histogramDriver(histogram, rH, rSize, 0);
return 0;
}
这是我期望的结果
当我从histogramDriver
调用outputHistogram(直方图,8)
(在cudaDeviceSynchronize()
之后)时,我看到以下内容:
0: 2 4
1: 1 3 5
2: EMPTY
3: EMPTY
4: EMPTY
5: EMPTY
6: EMPTY
7: EMPTY
0: EMPTY
1: EMPTY
2: EMPTY
3: EMPTY
4: EMPTY
5: EMPTY
6: EMPTY
7: EMPTY
显然,我没有正确地将值从设备复制回主机
我尝试过从historogramdriver
中的复制过程进行反向复制:
for(int i = 0; i < n; i++){
cudaMemcpy(&(tempData[i]), &(deviceHistogram[i].items), sizeof(int*), cudaMemcpyDeviceToHost);
}
for (int i = 0; i < n; i++) {
cudaMemcpy(histogram[i].items, tempData[i], rSize * sizeof(int), cudaMemcpyDeviceToHost);
}
for(int i=0;i
但是
outputHistogram
调用histogramDriver
的输出保持不变。正如@talonmies所指出的,这里最大的问题是内核的设计。没有理由/需要为直方图使用双指针(事实上,您发布的代码的第一次迭代在内核原型中没有,尽管它是不完整的)
通过删除双指针特性,代码运行时不会出现任何运行时错误
#include <stdlib.h>
#include <stdio.h>
#include "cuda.h"
typedef struct histogramBin {
int* items;
int count;
} histogramBin;
// This function embeds PTX code of CUDA to extract bit field from x.
__device__ uint bfe(uint x, uint start, uint nbits) {
uint bits;
asm("bfe.u32 %0, %1, %2, %3;"
: "=r"(bits)
: "r"(x), "r"(start), "r"(nbits));
return bits;
}
__global__ void makeHistogram(histogramBin* histogram, int* rH, int rSize, int bit) {
for (int r = 0; r < rSize; r++) {
int thisBin = bfe(rH[r], bit, 1);
int position = histogram[thisBin].count;
histogram[thisBin].items[position] = rH[r];
histogram[thisBin].count++;
}
}
void histogramDriver(histogramBin* histogram, int* rH, int rSize, int bit) {
int n = 8;
int* deviceRH;
histogramBin* deviceHistogram;
cudaMalloc((void**)&deviceRH, rSize * sizeof(int));
cudaMemcpy(deviceRH, rH, rSize * sizeof(int), cudaMemcpyHostToDevice);
cudaMalloc((void**)&deviceHistogram, n * sizeof(histogramBin));
cudaMemcpy(deviceHistogram, histogram, n * sizeof(histogramBin), cudaMemcpyHostToDevice);
int* tempData[n];
for (int i = 0; i < n; i++) {
cudaMalloc(&(tempData[i]), rSize * sizeof(int));
}
for (int i = 0; i < n; i++) {
cudaMemcpy(&(deviceHistogram[i].items), &(tempData[i]), sizeof(int*), cudaMemcpyHostToDevice);
}
for (int i = 0; i < n; i++) {
cudaMemcpy(tempData[i], histogram[i].items, rSize * sizeof(int), cudaMemcpyHostToDevice);
}
makeHistogram<<<1, 1>>>(deviceHistogram, deviceRH, rSize, bit);
cudaDeviceSynchronize();
}
int main(){
const int rSize = 5;
int rH[rSize] = {1, 2, 3, 4, 5};
histogramBin * histogram = (histogramBin*)malloc(sizeof(histogramBin) * 8);
for(int i = 0; i < 8; i++){
histogram[i].items = (int*)calloc(sizeof(int), rSize);
histogram[i].count = 0;
}
histogramDriver(histogram, rH, rSize, 0);
return 0;
}
$ nvcc t1452.cu -o t1452
$ cuda-memcheck ./t1452
========= CUDA-MEMCHECK
========= ERROR SUMMARY: 0 errors
$
#包括
#包括
#包括“cuda.h”
类型定义结构histogramBin{
国际*项目;
整数计数;
}组织grambin;
//该函数嵌入CUDA的PTX代码,从x中提取位字段。
__设备设备bfe(设备x、设备启动、设备nbits){
单位位元;
asm(“bfe.u32%0、%1、%2、%3
:“=r”(位)
:“r”(x),“r”(开始),“r”(nbits));
返回位;
}
__全局无效生成直方图(histogramBin*直方图,int*rH,int rSize,int位){
for(int r=0;r
请注意,这里唯一的更改是对内核代码本身的更改,加上删除了内核调用上的符号,再加上我在rSize
的定义中添加了const
,以获得要编译的内容
我不知道它是否产生正确的输出,因为您没有包括检查输出的方法,也没有指出您期望的输出是什么。如果您对此感兴趣,那么在您的MVE中加入这些内容将是一件好事。这是一份深入的副本,在
cuda
标签上有许多问题可以讨论。这是一个答案,列出了步骤并链接到几个示例。这是一个后续问题和答案。这是另一个答案,讨论了各种方法以及与几个示例的链接。请参阅2D分配。注意,第1项您应该提供一份您所展示的不是一份。它应该是一个完整的代码。makeHistogram(&deviceHistogram,…
显然是错误的。通过将主机变量的地址传递到内核,您希望实现什么?@RobertCrovella我已编辑添加了一个MVE。感谢您提供有关术语和参考的提示!这里的基本问题是犬舍的设计,而不是您如何复制这些天。我看不到任何有效的理由关于histogramBin**histogramBin**histogram
。为什么需要传递指向该犬舍的指针地址?谢谢你,罗伯特!我为不完整的MVE表示歉意;我已对其进行编辑,以便按照你的建议添加预期输出。