首页 > 其他分享 >vs2019-cuda配置入门

vs2019-cuda配置入门

时间:2023-08-28 13:55:10浏览次数:44  
标签:入门 vs2019 int cudaStatus dev 线程 cuda GPU 函数

cuda使用如下

1、打开VS,新建C++空项目

 2、右击源文件->添加->新建项

 3、选择CUDA C/C++ File,名称位main.cu

 4、把下面的示例源码复制到main.cu中

#include "cuda_runtime.h"
#include "device_launch_parameters.h"

#include <stdio.h>

/***************************************
 * 声明addWithCuda函数,这里是调用GPU运算的入口函数,函数的返回类型是cudaError_t。
 * cudaError_t是一个枚举类型,通常是和CUDA相关函数的返回类型,用于检测函数执行期间的不同类型错误,
 * 具体的定义在driver_types.h头文件中。如果执行成功,则返回0
***************************************/
cudaError_t addWithCuda(int* c, const int* a, const int* b, unsigned int size);

/***************************************
 * 声明addKernel核函数,函数的修饰符是__global__,提示编译器这个函数是在GPU上运行,所以会由NVCC来编译
   *
    __global__表示函数在device上运行,且须在host上调用,返回类型必须是void
    __device__表示函数在device上运行,只能在device上调用
    __host__表示函数在host上运行,只能在host上调用,可以省略不写,此函数在host和device上都编译
   *
 * threadIdx.x 表示获取执行当前计算任务的线程的ID号,并会在调用该函数时使用运行时配置符号“<<<>>>”确定线程数量。
   *
     GPU会根据这个索引号确定计算的线程资源。
     线程(thread)是GPU中的基本计算单位,各个线程相互独立计算,可以是一维,二维,三维
     线程块(block)是由一组线程组成的线程块,包含多个独立线程,可以是一维,二维,三维
     网格块(grid)是由一组多个网格块组成的网格块,包含多个独立线程块,可以是一维,二维
     通过指定grind-->block-->thread,可以确定具体线程资源
   *
 * 该核函数将会在GPU上被多个线程同时执行,线程间没有通信,相互独立。具体由哪些线程执行下会通过运行配置符“<<<>>>”确定
 * 具体为:<<<num,size>>> num表示分配了num个线程块(block),每个线程块分配了size个线程。num和size是1维,2维或是3维
 * “<<<>>>”中的参数并不是传递给device代码的参数,而是定义host代码运行时如何启动host代码
 * 这里的i可以理解维核函数会同时在不同的线程上运行,i表示线程号。
***************************************/
__global__ void addKernel(int* c, const int* a, const int* b)
{
    int i = threadIdx.x;
    c[i] = a[i] + b[i];
}

/***************************************
*  主函数
***************************************/
int main()
{
    // 初始化
    const int arraySize = 5;
    const int a[arraySize] = { 1, 2, 3, 4, 5 };
    const int b[arraySize] = { 10, 20, 30, 40, 50 };
    int c[arraySize] = { 0 };

    // 开始并行计算
    cudaError_t cudaStatus = addWithCuda(c, a, b, arraySize);
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "addWithCuda failed!");
        return 1;
    }

    printf("{1,2,3,4,5} + {10,20,30,40,50} = {%d,%d,%d,%d,%d}\n",
        c[0], c[1], c[2], c[3], c[4]);

    // cudaDeviceReset函数必须在结束程序前被调用,以便于分析完整的计算轨迹.
    cudaStatus = cudaDeviceReset();
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaDeviceReset failed!");
        return 1;
    }

    return 0;
}

/***************************************
 * 辅助函数,用于核函数执行的相关操作
***************************************/
cudaError_t addWithCuda(int* c, const int* a, const int* b, unsigned int size)
{
    int* dev_a = 0;
    int* dev_b = 0;
    int* dev_c = 0;
    cudaError_t cudaStatus;

    // 选择GPU号,在多GPU时可以选择特定的GPU号
    cudaStatus = cudaSetDevice(0);
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaSetDevice failed!  Do you have a CUDA-capable GPU installed?");
        goto Error;
    }

    // 分配GPU缓存,(两个输入,一个输出)
    cudaStatus = cudaMalloc((void**)&dev_c, size * sizeof(int));
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMalloc failed!");
        goto Error;
    }
    cudaStatus = cudaMalloc((void**)&dev_a, size * sizeof(int));
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMalloc failed!");
        goto Error;
    }
    cudaStatus = cudaMalloc((void**)&dev_b, size * sizeof(int));
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMalloc failed!");
        goto Error;
    }

    // 将输入向量从host内存中复制到GUP缓存中
    cudaStatus = cudaMemcpy(dev_a, a, size * sizeof(int), cudaMemcpyHostToDevice);
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMemcpy failed!");
        goto Error;
    }
    cudaStatus = cudaMemcpy(dev_b, b, size * sizeof(int), cudaMemcpyHostToDevice);
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMemcpy failed!");
        goto Error;
    }

    // 在GPU上启动一个内核,并分为每个元素分配线程
    addKernel << <1, size >> > (dev_c, dev_a, dev_b);

    // 在启动内核时,进行异常检测,返回最新的一个运行时调用错误
    cudaStatus = cudaGetLastError();
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "addKernel launch failed: %s\n", cudaGetErrorString(cudaStatus));
        goto Error;
    }

    // cudaDeviceSynchronize 函数等待内核计算完成,并返回运行状态 
    // any errors encountered during the launch.
        // 提供了一个阻塞,用于等待所有的线程都执行完各自的计算任务,然后继续往下执行
    cudaStatus = cudaDeviceSynchronize();
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaDeviceSynchronize returned error code %d after launching addKernel!\n", cudaStatus);
        goto Error;
    }

    // 从GPU缓存中将结果复制到host内存中
    cudaStatus = cudaMemcpy(c, dev_c, size * sizeof(int), cudaMemcpyDeviceToHost);
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMemcpy failed!");
        goto Error;
    }

Error:
    // 释放缓存
    cudaFree(dev_c);
    cudaFree(dev_a);
    cudaFree(dev_b);

    return cudaStatus;
}
Cuda示例代码

5、右击项目->生成依赖项->生成自定义,在弹出的对话框中选择CUDA

 6、右击main.cu文件->属性->项类型改为CUDA C/C++(注意配置:Debug  平台:x64)

 7、点击项目属性管理器->Debug | x64->添加现有属性表,并选择Cuda属性表

 8、直接调试输出结果(注意选择配置好的平台)

 

标签:入门,vs2019,int,cudaStatus,dev,线程,cuda,GPU,函数
From: https://www.cnblogs.com/lizhiqiang0204/p/17662103.html

相关文章

  • 【Ehcache技术专题】「入门到精通」带你一起从零基础进行分析和开发Ehcache框架的实战
    缓存大小的设置缓存大小的限制可以设置在CacheManager上,也可以设置在单个的Cache上。我们可以设置缓存使用内存的大小,也可以设置缓存使用磁盘的大小,但是使用堆内存的大小是必须设置的,其它可设可不设,默认不设就是无限制。在设置缓存大小的时候,我们可以设置缓存使用某一个存储器的最......
  • Linux基础入门常见命令
    ls查看ls-lcdmv移动mkdir创建df查看磁盘pwd查看当前目录rm-rf删除强制删除sudouseradd-m用户名创建新用户创建的新用户权限是很低的sudopasswd用户名创建新用户密码sudouserdel用户名删除用户sudormf-/home/用户名强制删除用户的所有......
  • 查看显卡相关信息(CUDA)
    右击进入NVIDIA控制面板......
  • 入门
    开始NodeGui使您能够使用JavaScript创建桌面应用程序。你可以看到它作为Node.js运行时的轻微修改变体,专注于桌面应用程序而不是网络服务器。NodeGui也是跨平台图形用户界面的高效JavaScript绑定。(图形用户界面)库.Qt是用于构建桌面应用程序的最成熟,最有效的库之......
  • EMQX简单入门
    最近项目上使用了mqtt协议来传输数据,之前没了解过,故简单学习下,本文作为学习记录以便之后复习使用。1.什么是MQTTMQTT 是一种基于发布/订阅模式的轻量级消息传输协议,专门针对低带宽和不稳定网络环境的物联网应用而设计,可以用极少的代码为联网设备提供实时可靠的消息服务。MQTT......
  • nginx从入门到实战
    概述异步非阻塞的高性能HTTP和反向代理服务器  nginx的运行架构 1、Master进程 启动检查nginx.conf是否正确 根据配置文件创建、监控worker进程的数量和状态 监听socket,接受client发起的请求,然后worker竞争抢夺连接,获胜的worker可以相应请求 接收管理员发送......
  • OpenGL入门——第一个三角形
    一、渲染管线在OpenGL中,任何事物都在3D空间中,而屏幕和窗口却是2D像素数组,所以由OpenGL的图形渲染管线将3D坐标转为2D坐标。图形渲染管线主要分为2个部分:第一部分将3D坐标转为2D坐标,第二部分把2D坐标转为实际的颜色像素。注意:2D坐标和像素也是不同的,2D坐标精确表示一个点在2D空......
  • 【Ehcache技术专题】「入门到精通」带你一起从零基础进行分析和开发Ehcache框架的实战
    Ehcache的存储方式Ehcache中对于缓存的存储主要有三种方式:分别是堆内存、非堆内存和磁盘。其中非堆内存是针对于企业版Ehcache才有的功能,它可以不受JavaGC的影响,能够创建很大的缓存。堆内存(MemoryStore)我们通常所有的MemoryStore实际上就是堆内存存储。MemoryStore总是可用的,所有......
  • kubernetes client-go快速入门及源码阅读
    client-go是kubernetes官方维护的一个go语言客户端,用于与k8s集群交互,使用client-go可以很方便的完成k8s的二次开发(似乎也必不可少),无论是稳定性还是健壮性都有充分的保障。client-go代码版本:v0.20.2个人水平有些,一定会出现不严谨或者错误的地方,如有错误麻烦评论指正,谢谢版......
  • opencv_contrib编译:fatal error: opencv2/xfeatures2d/cuda.hpp: No such file or dir
    在Ubuntu上编译opencv3.4.2源码时,遇到下面的错误,错误1:/home/src/software/opencv-3.4.2/modules/stitching/include/opencv2/stitching/detail/matchers.hpp:52:42:fatalerror:opencv2/xfeatures2d/cuda.hpp:Nosuchfileordirectory # include"opencv2/xfeatures2d/cud......