我有以下内容:
struct LR { double eps_dielect;
double sgm_conductivity;
double eno_ns_surfref;
double frq_mhz;
double conf;
double rel;
double erp;
int radio_climate;
int pol;
float antenna_pattern[361][1001];
} LR;
我需要将LR.antenna_pattern传递给一个函数,在CUDA设备中分配内存然后复制它。 float **类型应该代表LR.antenna_pattern [361] [1001]就好但我不知道如何实例化float **变量,以便它是一个指向LR.antenna_pattern的指针
我尝试浮动** antennaPattern =(void **)& LR.antenna_pattern但它不起作用。如何创建指向LR.antenna_pattern的指针?
答案 0 :(得分:1)
一种方法是展平您的2D数组并使用指针算法以1D方式处理它以处理行和列维度。首先在结构定义中,将antenna_pattern元素替换为:
struct LR {
.
.
float *antenna_pattern;
} LR;
然后你需要做一个主机端的malloc来分配空间:
#define COL 1001
#define ROW 361
#define DSIZE (ROW*COL)
LR.antenna_pattern = (float *)malloc(DSIZE*sizeof(float));
设备方面cuda malloc:
float *d_antenna_pattern;
cudaMalloc((void **) &d_antenna_pattern, DSIZE*sizeof(float));
设备的副本如下所示:
cudaMemcpy(d_antenna_pattern, LR.antenna_pattern, DSIZE*sizeof(float), cudaMemcpyHostToDevice);
如果要引用这些数组,则必须执行指针算法,如:
float my_val_xy = ap[(x*COL)+y]; // to access element at [x][y] on the device
float my_val_xy = LR.antenna_pattern[(x*COL)+y]; // on the host
如果要始终维护2D数组下标,可以使用适当的typedef执行此操作。有关示例,请参阅我对this question的回答中的第一个代码示例。要想出这个,你需要从typedef开始:
#define COL 1001
#define ROW 361
#define DSIZE (ROW*COL)
typedef float aParray[COL];
并修改您的结构定义:
struct LR {
.
.
aParray *antenna_pattern;
} LR;
主机侧malloc看起来像:
LR.antenna_pattern = (aParray *)malloc(DSIZE*sizeof(float));
设备端cuda malloc看起来像:
aParray *d_antenna_pattern;
cudaMalloc((void **) &d_antenna_pattern, DSIZE*sizeof(float));
设备的副本如下所示:
cudaMemcpy(d_antenna_pattern, LR.antenna_pattern, DSIZE*sizeof(float), cudaMemcpyHostToDevice);
设备内核定义需要一个函数参数,如:
__global__ void myKernel(float ap[][COL]) {
然后在内核中,您可以访问x,y处的元素:
float my_val_xy = ap[x][y];
现在回应一个后续问题,询问如果LR无法更改该怎么办,这里有一个完整的示例代码,它结合了其中一些想法而不修改LR结构:
#include<stdio.h>
// for cuda error checking
#define cudaCheckErrors(msg) \
do { \
cudaError_t __err = cudaGetLastError(); \
if (__err != cudaSuccess) { \
fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", \
msg, cudaGetErrorString(__err), \
__FILE__, __LINE__); \
fprintf(stderr, "*** FAILED - ABORTING\n"); \
return 1; \
} \
} while (0)
struct LR {
int foo;
float antenna_pattern[361][1001];
} LR;
__global__ void mykernel(float ap[][1001]){
int tid = threadIdx.x + (blockDim.x*blockIdx.x);
float myval = 0.0;
if (tid == 0){
for (int i=0; i<361; i++)
for (int j=0; j<1001; j++)
ap[i][j] = myval++;
}
}
int main(){
typedef float aParray[1001];
aParray *d_antenna_pattern;
cudaMalloc((void **) &d_antenna_pattern, (361*1001)*sizeof(float));
cudaCheckErrors("cudaMalloc fail");
float *my_ap_ptr;
my_ap_ptr = &(LR.antenna_pattern[0][0]);
for (int i=0; i< 361; i++)
for (int j=0; j<1001; j++)
LR.antenna_pattern[i][j] = 0.0;
cudaMemcpy(d_antenna_pattern, my_ap_ptr, (361*1001)*sizeof(float), cudaMemcpyHostToDevice);
cudaCheckErrors("cudaMemcpy fail");
mykernel<<<1,1>>>(d_antenna_pattern);
cudaCheckErrors("Kernel fail");
cudaMemcpy(my_ap_ptr, d_antenna_pattern, (361*1001)*sizeof(float), cudaMemcpyDeviceToHost);
cudaCheckErrors("cudaMemcpy 2 fail");
float myval = 0.0;
for (int i=0; i<361; i++)
for (int j=0; j<1001; j++)
if (LR.antenna_pattern[i][j] != myval++) {printf("mismatch at offset x: %d y: %d actual: %f expected: %f\n", i, j, LR.antenna_pattern[i][j], --myval); return 1;}
printf("Results match!\n");
return 0;
}
如果您更喜欢使用拼合方法,请将d_antenna_pattern
定义替换为:
float *d_antenna_pattern;
并相应地更改内核函数参数:
__global__ void mykernel(float *ap){
然后使用内核中的指针算术方法进行访问:
ap[(i*1001)+j] = myval++;