cuda编程入门示例3---数组求和

本文介绍了一个使用CUDA进行并行计算的例子——计算数组中所有元素的平方和。代码中包含了错误处理机制、数据生成、CUDA初始化及设备选择等功能,并对比了GPU与CPU计算结果的一致性。

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

#include <stdio.h>
#include <stdlib.h>
#include <cuda_runtime.h>

#define BLOCK_SIZE 16
static void HandleError(cudaError_t err, const char *file, int line)
{
	if (err != cudaSuccess)
	{
		printf("%s in %s at line %d\n", cudaGetErrorString(err), file, line);
		exit(EXIT_FAILURE);
	}
}
#define HANDLE_ERROR( err ) (HandleError( err, __FILE__, __LINE__ ))

#define HANDLE_NULL( a ) {if ((a) == NULL) { \
	printf("Host memory failed in %s at line %d\n", \
	__FILE__, __LINE__); \
	exit(EXIT_FAILURE); }}

static void GenerateNumbers(int *number, int size)
{
	for (int i = 0; i < size; i++)
	{
		//注意int型数据溢出
		number[i] = rand() % 10;
	}
}

static bool InitCUDA()
{
	int count;

	cudaGetDeviceCount(&count);
	if (count == 0)
	{
		fprintf(stderr, "There is no device.\n");
		return false;
	}

	int i;
	for (i = 0; i < count; i++)
	{
		cudaDeviceProp prop;
		if (cudaGetDeviceProperties(&prop, i) == cudaSuccess)
		{
			if (prop.major >= 1)
			{
				break;
			}
		}
	}

	if (i >= count)
	{
		fprintf(stderr, "There is no device supporting CUDA 1.x.\n");
		return false;
	}

	cudaSetDevice(i);

	return true;
}

__global__ static void sumOfSquares(int *num, int size, int* result)
{
	int sum = 0;

	for (int i = 0; i < size; i++)
	{
		sum += num[i] * num[i];
	}
	*result = sum;
}

int main(int argc, char *argv[])
{
	if (!InitCUDA())
	{
		return -1;
	}
	printf("CUDA initialized.\n");

	//对一个数组求和:每个元素相加
	const int DATA_SIZE = 256;
	int data[DATA_SIZE];
	GenerateNumbers(data, DATA_SIZE);

	int* gpudata, *result;
	HANDLE_ERROR(cudaMalloc((void **)&gpudata, sizeof(int)* DATA_SIZE));
	HANDLE_ERROR(cudaMalloc((void**)&result, sizeof(int)));
	HANDLE_ERROR(cudaMemcpy(gpudata, data, sizeof(int)* DATA_SIZE, cudaMemcpyHostToDevice));

	sumOfSquares<<<1, 1, 0 >>>(gpudata, DATA_SIZE, result);

	int sum;
	HANDLE_ERROR(cudaMemcpy(&sum, result, sizeof(int), cudaMemcpyDeviceToHost));

	cudaFree(gpudata);
	cudaFree(result);

	printf("sum (GPU): %d\n", sum);

	int sumCPU = 0;
	for (int i = 0; i < DATA_SIZE; i++)
	{
		sumCPU += data[i] * data[i];
	}
	printf("sum (CPU): %d\n", sumCPU);

	printf("Result %s\n", sum == sumCPU ? "OK" : "Wrong");

	//remember to release the device
	cudaDeviceReset();

	return 0;
}

<think>嗯,用户之前已经问过MPI并行编程的基本概念以及它与C++和Python的关系,现在他们表示自己完全不了解,应该从哪里开始学起。我需要先回顾之前的对话内容,确保这次回答连贯且有针对性。用户可能是一个刚接触并行编程的新手,可能没有太多编程经验,或者至少对MPI完全陌生。他们的需求是明确的学习路径,需要从基础开始逐步引导。 首先,用户的问题是关于学习路径的,所以需要分步骤、结构清晰。之前的回答已经介绍了MPI的基本概念、与编程语言的关系,现在需要提供一个入门指南。需要考虑用户可能的背景:是否有编程基础?是否有并行计算的概念?由于用户说“完全不了解”,可能假设他们编程基础较弱,或者至少对并行计算不了解。 接下来,我需要确定学习MPI的关键步骤。通常,学习MPI需要先掌握基本的编程技能,比如C或Python,然后理解并行计算的基本概念,如进程、通信等。然后逐步学习MPI的API,从点对点通信到集体通信,最后到高级话题。同时,实践和调试也是重要的部分。 需要确保回答的结构清晰,分点明确,让用户容易跟随。可能需要包括以下几个部分:预备知识、MPI核心概念、学习资源、实践建议、常见误区等。另外,考虑到用户可能更倾向于使用Python,可能需要同时提到C/C++和Python的选择,但根据之前的回答,用户可能对Python更感兴趣,所以可能需要强调Python的mpi4py库。 还要注意避免使用过于专业的术语,用通俗易懂的语言解释概念,比如消息传递、进程间通信等。同时,可能需要推荐一些具体的学习资源,如书籍、在线教程、实践平台等,帮助用户找到学习材料。 另外,用户可能没有接触过MPI环境配置,可能需要指导如何安装MPI库,比如OpenMPI或MPICH,以及如何配置开发环境,这对于新手来说可能是一个障碍。或者,如果用户使用Python的mpi4py,安装步骤可能更简单,可以推荐他们从Python入手,降低入门难度。 还需要考虑用户的学习目标,是学术研究、工业应用还是个人兴趣?根据之前的回答,应用场景包括科学计算、大数据处理、机器学习,可能需要针对这些领域给出具体的学习建议,但用户当前阶段可能需要更基础的内容。 最后,要鼓励用户动手实践,因为MPI编程需要实际操作才能掌握,尤其是调试分布式程序的经验。可能建议他们从简单的例子开始,逐步增加复杂度,并参与社区或论坛寻求帮助。</think>以下是针对**零基础学习者**的MPI入门路径,分步骤解析: --- ### **第一步:巩固编程与并行计算基础** 1. **掌握一门宿主语言** - **推荐选择**:C/C++(高性能场景)或Python(快速上手)。 - **关键知识点**: - C/C++:指针、数组、函数调用。 - Python:基础语法、面向对象编程。 2. **理解并行计算基本概念** - **进程 vs 线程**: - 进程:独立内存空间,通过**消息传递**通信(MPI的核心)。 - 线程:共享内存,通过**锁/信号量**同步(如OpenMP)。 - **分布式内存模型**:每个进程只能直接访问自己的内存,跨进程数据需显式传输。 --- ### **第二步:学习MPI核心API(从简单到复杂)** 1. **环境配置与Hello World** - **安装MPI实现**: - C/C++:安装[OpenMPI](https://www.open-mpi.org/)或[MPICH](https://www.mpich.org/)。 - Python:通过`pip install mpi4py`安装库。 - **第一个MPI程序**: ```python # Python示例(mpi4py) from mpi4py import MPI comm = MPI.COMM_WORLD rank = comm.Get_rank() print(f"我是进程 {rank}/{comm.Get_size()}") ``` - 运行命令:`mpiexec -n 4 python hello.py`(启动4个进程)。 2. **掌握基础通信操作** - **点对点通信**: | 函数 | 作用 | |-----------------|--------------------------| | `MPI_Send()` | 发送消息到指定进程 | | `MPI_Recv()` | 接收来自指定进程的消息 | - **集体通信**(集体操作): | 函数 | 作用 | |-----------------|--------------------------| | `MPI_Bcast()` | 将数据从根进程广播到所有进程 | | `MPI_Reduce()` | 将各进程数据聚合(如求和) | - **示例**:计算$\pi$的并行积分法(Python片段): ```python from mpi4py import MPI import numpy as np comm = MPI.COMM_WORLD rank = comm.Get_rank() size = comm.Get_size() # 每个进程计算局部积分 n = 1000000 # 总采样点 local_n = n // size x = np.random.uniform(0, 1, local_n) local_pi = 4 * np.sum(np.sqrt(1 - x**2)) / n # 聚合结果到根进程 total_pi = comm.reduce(local_pi, op=MPI.SUM, root=0) if rank == 0: print(f"π ≈ {total_pi}") ``` --- ### **第三步:进阶学习与实战** 1. **深入理解通信模式** - **阻塞 vs 非阻塞通信**: - 阻塞操作(如`MPI_Send`)等待通信完成才继续执行。 - 非阻塞操作(如`MPI_Isend`)立即返回,通过`MPI_Wait`检查状态。 - **通信器(Communicator)**:管理进程组(如`MPI_COMM_WORLD`)。 2. **调试与性能优化** - **工具推荐**: - 调试:使用`printf`分步输出,或专用工具[Valgrind](https://www.valgrind.org/)。 - 性能分析:利用[MPI Profiler](https://www.mcs.anl.gov/research/projects/perfvis/software/MPE/)可视化通信开销。 3. **实战项目参考** - **初级**:并行矩阵乘法、蒙特卡洛模拟。 - **中级**:实现分布式排序(如归并排序)。 - **高级**:结合CUDA实现CPU-GPU混合并行。 --- ### **学习资源推荐** | 类型 | 资源名称 | 特点 | |------------|--------------------------------------------------------------------------|-------------------------------| | **书籍** | 《并行程序设计导论》(Using MPI) | 经典教材,C/MPI代码示例 | | **教程** | [MPI Tutorial](https://mpitutorial.com/) | 交互式学习,适合零基础 | | **视频** | [B站:MPI并行编程入门](https://www.bilibili.com/video/BV1XQ4y1A7kC) | 中文讲解,手把手配置环境 | | **社区** | [Stack Overflow MPI标签](https://stackoverflow.com/questions/tagged/mpi) | 解决具体问题的实战问答 | --- ### **避坑指南** 1. **避免死锁**:确保`Send`和`Recv`的进程与标签匹配。 2. **注意数据类型**:C/C++中`int`与Python的`int`可能不兼容,需显式指定。 3. **性能陷阱**:频繁小消息通信会显著降低效率,尽量批量传输数据。 --- **总结**:MPI学习需**循序渐进**,先理解进程通信逻辑,再通过项目积累经验。从单机多进程实验开始,逐步扩展到集群环境。遇到问题时,善用调试工具和社区资源!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值