【发布时间】:2019-11-26 21:14:10
【问题描述】:
我在使用此 cuda 代码中动态分配的成员变量的结构数组的深层副本时遇到问题。我认为这是因为&deviceHistogram 指向主机上的地址而不是设备上的地址。我尝试在here 中创建一个中间指针变量,但这不起作用;如何正确复制整个结构数组,以便可以从 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;
}
一旦它被正确复制到设备上,我如何将它恢复到主机上?例如,如果我从 makeHistogram 内部调用 outputHistogram(histogram, 5);,我会看到以下内容:
0: 2 4
1: 1 3 5
2: EMPTY
3: EMPTY
4: EMPTY
5: EMPTY
6: EMPTY
7: EMPTY
这是我期望的输出。
当我从histogramDriver(cudaDeviceSynchronize() 之后)呼叫outputHistogram(histogram, 8) 时,我看到以下内容:
0: EMPTY
1: EMPTY
2: EMPTY
3: EMPTY
4: EMPTY
5: EMPTY
6: EMPTY
7: EMPTY
显然我没有正确地将值从设备复制回主机。
我尝试通过与histogramDriver 中的相反的过程进行复制:
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);
}
但histogramDriver 中的outputHistogram 调用的输出保持不变。
【问题讨论】:
-
注意项目 1 here 你应该提供一个 minimal reproducible example 你显示的不是一个。应该是完整的代码。
-
makeHistogram<<<1, 1>>>(&deviceHistogram, .....显然是错误的。您希望通过将主机变量的地址传递给内核来实现什么? -
@RobertCrovella 我已编辑以添加 MVE。感谢您提供有关术语和参考的指示!
-
这里的基本问题是你的狗窝的设计,而不是你如何复制日子。我认为
histogramBin** histogram没有正当理由。为什么需要将指针的地址传递给该犬舍?
标签: cuda