主机(CPU)和设备(GPU)内存函数
标准C | CUDA C | 标准C | CUDA C |
malloc | cudaMalloc | memset | cudaMemset |
memcpy | cudaMemcpy | free | cudaFree |
cudaError_t cudaMalloc(void** devPtr, size_t size)
该函数负责向设备分配一定字节的线性内存。
cudaError_t cudaMemcpy(void* dst, const void* src, size_t count, cudaMemcpyKind kind)
该函数从src指向的源存储区中复制一定数量的字节到dst指向的目标存储区,复制方向由kind制定:
cudaMemcpyHostToHost、cudaMemcpyHostToDevice、cudaMemcpyDeviceToHost、cudaMemcpyDeviceToDevice
除了内核启动之外的CUDA调用都会返回一个错误的枚举类型cudaErro_t。如果GPU 内存分配成功,函数返回cudaSuccess,否则返回cudaErrorMemoryAllocation。
可以使用 char* cudaGetErrorString(cudaError_t error)函数将错误代码转化为可读的错误信息。此函数和strerror函数类似。
下面看一个求和的例子:
C++代码:
#include <stdio.h>
void sumArray(int *A, int *B, int *C,const int N)
{
for(int i = 0; i < N; ++i)
{
C[i] = A[i] + B[i];
}
}
int main()
{
int *A = new int[1000]();
int *B = new int[1000]();
int *C = new int[1000]();
int result = 0;
for(int i = 0; i < 1000; ++i)
{
A[i] = i;
B[i] = i + 1000;
}
sumArray(A,B,C,1000);
for(int i = 0; i < 1000; ++i)
{
result = result + C[i];
}
printf("result:%d\n",result);
}
cuda代码:
#include <stdio.h>
#include <stddef.h>
#include <cuda_runtime.h>
__global__ void sumArrayCu(int *A, int *B, int *C,const int N)
{
int i = threadIdx.x;
C[i] = A[i] + B[i];
//printf("i = %d c[i] = %d\n",i,C[i]);
}
/*不能直接调用核函数,CPU内存GPU无法直接访问
int main()
{
int *A = new int[1000]();
int *B = new int[1000]();
int *C = new int[1000]();
int result = 0;
for(int i = 0; i < 1000; ++i)
{
A[i] = i;
B[i] = i + 1000;
}
sumArrayCu <<<1,10>>>(A,B,C,1000);
for(int i = 0; i < 10; ++i)
{
result = result + C[i];
}
printf("result:%d\n",result);
cudaDeviceReset();
}*/
int main()
{
int *A = NULL,*B = NULL,*C = NULL;
cudaMallocManaged((void**)&A,1000*sizeof(int)); //采用统一内存
cudaMallocManaged((void**)&B,1000*sizeof(int));
cudaMallocManaged((void**)&C,1000*sizeof(int));
int result = 0;
for(int i = 0; i < 1000; ++i)
{
A[i] = i;
B[i] = i + 1000;
}
sumArrayCu <<<1,1000>>>(A,B,C,1000);
cudaDeviceSynchronize(); /*CUDA调用是异步的,必须要在主机端显式同步,否则会出现设备端
与主机端同时访问统一内存,其实就是主机线程等待核函数执行完毕*/
for(int i = 0; i < 1000; ++i)
{
result = result + C[i];
}
printf("result:%d\n",result);
cudaDeviceReset();
}
两者的结果是一致的。