就有关CUDA的教程而言,大多数数据是通过内核调用发送到Device的。我想知道是否有我可以表演 初始化数据-进程-清理cuda中的某种操作。这是我尝试的代码,但似乎不起作用。
#include <cuda.h>
#include <stdio.h>
#include <cuda_runtime.h>
#define CUDA_CHECK_VALUE(value, a) { \
cudaError_t _m_cudaStatus = value; \
if(_m_cudaStatus != cudaSuccess) { \
printf("Error &s at line %d in file %s\n", \
cudaGetErrorString(_m_cudaStatus), \
__LINE__, __FILE__); \
exit(1); \
} else {printf("Done! - %d\n", a);} }
__constant__
float* data;
__host__ __device__
void initMemory(int size){
CUDA_CHECK_VALUE(cudaMalloc(&data, sizeof(float) * size), 0);
float *ha = new float[size];
for(int i =0; i < size; i++){
ha[i] = i * 1.0f;
}
CUDA_CHECK_VALUE(cudaMemcpyToSymbol(data, ha, sizeof(float) * size, 0, cudaMemcpyHostToDevice), 1);
CUDA_CHECK_VALUE(cudaDeviceSynchronize(), 2);
}
__host__ __device__
void freeMemory(){
CUDA_CHECK_VALUE(cudaDeviceSynchronize(), 3);
cudaFree(data);
}
__global__
void print(int size){
printf("size = %d\n", size);
for(int i = 0; i < size; i++){
printf("data[%d] = %f\n", i, data[i]);
}
}
int main(){
int size = 1024;
initMemory(size);
printf("1\n");
print<<<1, 1>>>(size);
printf("2\n");
cudaDeviceSynchronize();
freeMemory();
printf("3\n");
}
在这段代码中,我试图将一些数据由主机初始化一次,并为多次调用准备内核进程,并最终通过清理方法释放cuda内存。但是我不确定这是否是使用CUDA的正确方法,以及如何相应地修改我的代码。
答案 0 :(得分:2)
可以说的很公平,可以说在问题中显示的两个版本的代码中几乎都有错误。因此,比起解释两次尝试中的所有不正确之处,更容易显示工作版本的样子:
#include <cuda.h>
#include <stdio.h>
#include <cuda_runtime.h>
#define CUDA_CHECK_VALUE(value, a) { \
cudaError_t _m_cudaStatus = value; \
if(_m_cudaStatus != cudaSuccess) { \
printf("Error %s at line %d in file %s\n", \
cudaGetErrorString(_m_cudaStatus), \
__LINE__, __FILE__); \
exit(1); \
} else {printf("Done! - %d\n", a);} }
__device__ float* data;
void initMemory(int size){
float* da;
CUDA_CHECK_VALUE(cudaMalloc(&da, sizeof(float) * size), 0);
float *ha = new float[size];
for(int i =0; i < size; i++){
ha[i] = i * 1.0f;
}
CUDA_CHECK_VALUE(cudaMemcpy(da, ha, sizeof(float) * size, cudaMemcpyHostToDevice), 1);
CUDA_CHECK_VALUE(cudaMemcpyToSymbol(data, &da, sizeof(da), 0, cudaMemcpyHostToDevice), 2);
CUDA_CHECK_VALUE(cudaDeviceSynchronize(), 3);
delete[] ha;
}
void freeMemory(){
CUDA_CHECK_VALUE(cudaDeviceSynchronize(), 4);
float* da;
CUDA_CHECK_VALUE(cudaMemcpyFromSymbol(&da, data, sizeof(da), 0, cudaMemcpyDeviceToHost), 5);
CUDA_CHECK_VALUE(cudaFree(da), 6);
}
__global__
void print(int size){
for(int i = 0; i < size; i++){
printf("data[%d] = %f\n", i, data[i]);
}
}
int main(){
int size = 1024;
initMemory(size);
printf("1\n");
print<<<1, 1>>>(size);
cudaDeviceSynchronize();
printf("2\n");
freeMemory();
printf("3\n");
}
几点:
initMemory
和freeMemory
都在代码中的主机上运行很重要。用__device__
装饰代码不会自动使代码在设备上运行。它仅将代码的版本编译为设备功能,可以在内核中调用。但是,您实际上根本不会执行此操作,因此所有代码都在主机上运行,因为这就是您调用它的位置。__shared__
和__constant__
的内存无法从主机上动态分配,就像您在我们看到的两次代码迭代中所尝试的那样initMemory
和freeMemory
的第二种实现中需要使用许多附加的CUDA主机API函数,以使事情正常运行,这在上面的代码中显而易见。