基于 cuda 的并行矢量和

本文详细介绍了CUDA并行编程的基本概念,包括如何使用cudaMalloc动态分配GPU内存,__global__修饰符在核函数中的应用,以及线程块和线程ID的使用。通过实例演示了如何在Cuda中实现基本的加法运算,并展示了内存管理和数据复制的重要步骤。
摘要由CSDN通过智能技术生成

CUDA 并行编程

#include <iostream>

#include <cuda.h>
#include <driver_types.h>
#include <device_launch_parameters.h>


#include "utils.h"

#define N 10

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__ ))


__global__ void add(int *a, int *b, int *c)
{
    int tid = blockIdx.x;   // 该索引处的数据
    if (tid < N)
    {
        c[tid] = a[tid] + b[tid];
    }
}


int main()
{

    int a[N], b[N], c[N];
    int *dev_a, *dev_b, *dev_c;

    // 在 GPU 上分配内存

    HANDLE_ERROR(cudaMalloc( (void**)&dev_a, N * sizeof(int) ) );
    HANDLE_ERROR(cudaMalloc( (void**)&dev_b, N * sizeof(int) ) );
    HANDLE_ERROR(cudaMalloc( (void**)&dev_c, N * sizeof(int) ) );

    // 在 CPU 上为数组 "a" 和 "b"赋值
    for (int i=0; i<N;i++)
    {
        a[i] = -i;
        b[i] = i*i;

    }

    // 将数组 "a" 和 "b" 复制到 GPU

    HANDLE_ERROR(cudaMemcpy(dev_a, a, N * sizeof(int), cudaMemcpyHostToDevice));
    HANDLE_ERROR(cudaMemcpy(dev_b, b, N * sizeof(int), cudaMemcpyHostToDevice));

    add<<<N, 1>>>(dev_a, dev_b, dev_c);

    // 将数组 "c" 从 GPU 复制到 CPU

    HANDLE_ERROR(cudaMemcpy(c, dev_c, N* sizeof(int), cudaMemcpyDeviceToHost));

    // 显示结果

    for (int i=0;i<N;i++)
    {
        printf("%d + %d = %d\n", a[i], b[i], c[i]);
    }

    // 释放在 GPU上分配的内存
    cudaFree(dev_a);
    cudaFree(dev_b);
    cudaFree(dev_c);

    return 0;
}
  • 调用 cudaMalloc() 在设备上为三个数组分配内存,其中两个数组 dev_adev_b 中包含 输入值,而在数组 dev_c 中包含了计算结果.
  • 为了鼻尖内存泄露,在使用完 GPU 内存后,通过 cudaFree() 释放内存.
  • 通过 cudaMemcpy() 将输入 数据复制到设备中,同时指定参数cudaMemcpyHostToDevice, 在计算完记过,通过参数 cudaMemcpyDeviceToHost 复制回主机.
  • 通过尖括号语法,在主机代码 main() 中执行 add() 中的设备代码.
  • __global__ 修饰符
  • 我们增看到过通过以下形式启动的核函数 kernel<<<1, 1>>>(param1, param2, ...)
  • add<<<N, 1>>>(dev_a, dev_b, dev_c) 第一个参数表示设备执行核函数时,使用的并行线程块的数量,指定这个参数为 N
  • 为什么不是 blockIdx, 而是 blockIdx.x, 事实上因为 CUDA支持二维的线程块数组,当启动核函数时,我们将并行线程块数量指定 N, 这个并行线程块集合也成为一个线程格 Grid, 我们使用的是一维的线程则,第一个线程块的blockIdx.x=0, 最后一个线程块 blockIdx.x=N-1. 第二个参数是每个线程块中使用一个线程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值