2、CUDA编程简介与统一内存实践

本文介绍了CUDA中如何进行内存分配、数据拷贝及设备计算,通过C++代码和CUDA代码对比展示了如何利用GPU加速计算。CUDA的cudaMalloc、cudaMemcpy和cudaMemset用于设备内存管理,而cudaMemcpy负责数据传输。示例中展示了求和操作在CPU和GPU上的实现,并强调了CUDA调用的异步特性及同步需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

                                                                                                                               主机(CPU)和设备(GPU)内存函数

标准CCUDA C标准CCUDA C
malloccudaMallocmemsetcudaMemset
memcpycudaMemcpyfreecudaFree

    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();
}

两者的结果是一致的。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值