第一个CUDA程序-addVector

2023-10-26

本文主要通过对两个浮点数组中的数据进行相加,并将其结果放入第三个数组中。其算法分别在CPU、GPU上分别执行,并比较了所需时间,强烈感受到GPU的并行计算能力。这里,每个数组的元素大小为30000000个。

一、实现代码

[cpp]  view plain  copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <time.h>  
  4. #include <math.h>  
  5.   
  6. // For the CUDA runtime routines (prefixed with "cuda_")  
  7. #include <cuda_runtime.h>  
  8.   
  9. //该函数声明为了__global__,表示由GPU调用执行.  
  10. //其功能为将数组pA、pB中对应位置的数据相加,并将结果放入数组pC的对应位置上  
  11. //每个数组的索引大小为size  
  12. __global__  
  13. void add(const float * pA, const float * pB, float * pC, unsigned int size)  
  14. {  
  15.     int index = blockIdx.x * blockDim.x + threadIdx.x;      //计算当前数组中的索引  
  16.     if (index < size)                                        //确保是一个有效的索引  
  17.         pC[index] = pA[index] + pB[index];  
  18.   
  19. }  
  20.   
  21. int main()  
  22. {  
  23.     unsigned int numElement = 30000000;  
  24.     int totalSize = sizeof(float)* numElement;  
  25.   
  26.     //init  
  27.     float *pA = (float*)malloc(totalSize);  
  28.     float *pB = (float*)malloc(totalSize);  
  29.     float *pC = (float*)malloc(totalSize);  
  30.   
  31.     for (int i = 0; i < numElement; ++i)  
  32.     {  
  33.         *(pA + i) = rand() / (float)RAND_MAX;;  
  34.         *(pB + i) = rand() / (float)RAND_MAX;  
  35.     }  
  36.   
  37.     //cpu segment  
  38.   
  39.     //begin use cpu comput  
  40.     clock_t startTime, endTime;  
  41.     startTime = clock();  
  42.     for (int i = 0; i < numElement; ++i)  
  43.     {  
  44.         *(pC + i) = *(pA + i) + *(pB + i);  
  45.     }  
  46.     endTime = clock();  
  47.     //end use cpu comput  
  48.   
  49.     printf("use cpu comput finish!\n");  
  50.     printf("use total time = %fs\n", (endTime - startTime) / 1000.f);  
  51.     printf("\n\n");  
  52.   
  53.   
  54.     //gpu segment  
  55.     float *pD, *pE, *pF;  
  56.     cudaError_t err = cudaSuccess;  
  57.   
  58.     //malloc memory  
  59.     err = cudaMalloc(&pD, totalSize);  
  60.     if (err != cudaSuccess)  
  61.     {  
  62.         printf("call cudaMalloc fail for pD.\n");  
  63.         exit(1);  
  64.     }  
  65.   
  66.     err = cudaMalloc(&pE, totalSize);  
  67.     if (err != cudaSuccess)  
  68.     {  
  69.         printf("call cudaMalloc fail for pE.\n");  
  70.         exit(1);  
  71.     }  
  72.   
  73.     err = cudaMalloc(&pF, totalSize);  
  74.     if (err != cudaSuccess)  
  75.     {  
  76.         printf("call cudaMalloc fail for pF.\n");  
  77.         exit(1);  
  78.     }  
  79.   
  80.     //copy data  from pA pB pC to pD pE pF  
  81.     err = cudaMemcpy(pD, pA, totalSize, cudaMemcpyHostToDevice);  
  82.     if (err != cudaSuccess)  
  83.     {  
  84.         printf("call cudaMemcpy fail for pA to pD.\n");  
  85.         exit(1);  
  86.     }  
  87.   
  88.     err = cudaMemcpy(pE, pB, totalSize, cudaMemcpyHostToDevice);  
  89.     if (err != cudaSuccess)  
  90.     {  
  91.         printf("call cudaMemcpy fail for pB to pE.\n");  
  92.         exit(1);  
  93.     }  
  94.   
  95.   
  96.     //begin use gpu comput  
  97.     startTime = clock();  
  98.     int threadPerBlock = 1024;  
  99.     int numBlock = (numElement - 1) / threadPerBlock + 1;  
  100.     add << <numBlock, threadPerBlock >> >(pD, pE, pF, numElement);  
  101.   
  102.     err = cudaGetLastError();  
  103.     if (err != cudaSuccess)  
  104.     {  
  105.         printf("use gpu comput fail!\n");  
  106.         exit(1);   
  107.     }  
  108.   
  109.     endTime = clock();  
  110.     printf("use gpu comput finish!\n");  
  111.     printf("use time : %fs\n",(endTime - startTime) / 1000.f);  
  112.     //end use gpu comput  
  113.   
  114.   
  115.     //copu data from device to host  
  116.     err = cudaMemcpy(pC, pF, numElement, cudaMemcpyDeviceToHost);  
  117.     if (err != cudaSuccess)  
  118.     {  
  119.         printf("call cudaMemcpy form pF to pC fail.\n");  
  120.         exit(1);  
  121.     }  
  122.   
  123.     //check data  
  124.     for (int i = 0; i < numElement; ++i)  
  125.     {  
  126.         if (fabs(pA[i] + pB[i] - pC[i]) > 1e-5)  
  127.         {  
  128.             printf("%f + %f != %f\n",pA[i],pB[i],pC[i]);  
  129.         }  
  130.     }  
  131.   
  132.     //释放设备上的内存  
  133.     cudaFree(pD);  
  134.     cudaFree(pE);  
  135.     cudaFree(pF);  
  136.   
  137.     //在程序退出前,调用该函数重置该设备,使驱动去清理设备状态,并且在程序退出前所有的数据将被刷出。  
  138.     err = cudaDeviceReset();  
  139.     if (err != cudaSuccess)  
  140.     {  
  141.         printf("call cudaDeviceReset fail!\n");  
  142.         exit(1);  
  143.     }  
  144.   
  145.     free(pA);  
  146.     free(pB);  
  147.     free(pC);  
  148.   
  149.     getchar();  
  150.     return 0;  
  151. }  


二、运行结果






三、部分CUDA函数说明


1、cudaMalloc

[cpp]  view plain  copy
  1. __host__  cudaError_t  cudaMalloc(void **devPtr, size_t size);  
        该函数主要用来分配设备上的内存(即显存中的内存)。该函数被声明为了__host__,即表示被host所调用,即在cpu中执行的代码所调用。
        返回值:为cudaError_t类型,实质为cudaError的枚举类型,其中定义了一系列的错误代码。如果函数调用成功,则返回cudaSuccess。
        第一个参数,void ** 类型,devPtr:用于接受该函数所分配的内存地址
        第二个参数,size_t类型,size:指定分配内存的大小,单位为字节

2、cudaFree

[cpp]  view plain  copy
  1. __host__  cudaError_t  cudaFree(void *devPtr);  
        该函数用来释放先前在设备上申请的内存空间(通过cudaMalloc、cudaMallocPitch等函数),注意,不能释放通过标准库函数malloc进行申请的内存。
        返回值:为错误代码的类型值
        第一个参数,void**类型,devPtr:指向需要释放的设备内存地址

3、cudaMemcpy

[cpp]  view plain  copy
  1. __host__ cudaError_t  cudaMemcpy(void *dst, const void *src, size_t count, enum cudaMemcpyKind kind);  
        该函数主要用于将不同内存段的数据进行拷贝,内存可用是设备内存,也可用是主机内存
        第一个参数,void*类型,dst:为目的内存地址
        第二个参数,const void *类型,src:源内存地址
        第三个参数,size_t类型,count:将要进行拷贝的字节大小
        第四个参数,enum cudaMemcpyKind类型,kind:拷贝的类型,决定拷贝的方向
cudaMemcpyKind类型如下:
[cpp]  view plain  copy
  1. enum __device_builtin__ cudaMemcpyKind  
  2. {  
  3.     cudaMemcpyHostToHost          =   0,      /**< Host   -> Host */  
  4.     cudaMemcpyHostToDevice        =   1,      /**< Host   -> Device */  
  5.     cudaMemcpyDeviceToHost        =   2,      /**< Device -> Host */  
  6.     cudaMemcpyDeviceToDevice      =   3,      /**< Device -> Device */  
  7.     cudaMemcpyDefault             =   4       /**< Default based unified virtual address space */  
  8. };  
cudaMemcpyKind决定了拷贝的方向,即是从主机的内存拷贝至设备内存,还是将设备内存拷贝值主机内存等。cudaMemcpy内部根据拷贝的类型(kind)来决定调用以下的某个函数:
[cpp]  view plain  copy
  1. ::cudaMemcpyHostToHost,   
  2. ::cudaMemcpyHostToDevice,   
  3. ::cudaMemcpyDeviceToHost,  
  4. ::cudaMemcpyDeviceToDevice  

4、cudaDeviceReset

[cpp]  view plain  copy
  1. __host__ cudaError_t  cudaDeviceReset(void);  
        该函数销毁当前进程中当前设备上所有的内存分配和重置所有状态,调用该函数达到重新初始该设备的作用。应该注意,在调用该函数时,应该确保该进程中其他host线程不能访问该设备!

Last:源程序下载地址
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

第一个CUDA程序-addVector 的相关文章

  • 使用 CUDA 占用计算器

    我正在使用占用率计算器 但我无法理解如何获取每个线程的寄存器 每个块的共享内存 我阅读了文档 我使用 Visual Studio 所以在 CUDA 构建规则下的项目属性中 gt 命令行 gt 附加选项 I添加 ptxas options v
  • CUDA:同步线程

    几乎在我读到的有关 CUDA 编程的任何地方都提到了 warp 中的所有线程都执行相同操作的重要性 在我的代码中 我遇到了无法避免某种条件的情况 它看起来像这样 some math code calculating d1 d2 if d1
  • 如何使用 eclipse Nsight 仅使用一个 GPU 调试 CUDA

    我收到错误 所有 cuda 设备均用于显示 在调试时无法使用 使用Ubuntu 有没有什么方法可以使用 Nsight eclipse 仅使用一个 GPU 进行调试 我见过类似的解决方案 sudo 服务 lightdm 停止 杀死 X 但这也
  • 如何实现设备端CUDA虚拟功能?

    我发现 CUDA 不允许将具有虚拟函数的类传递到内核函数中 对于这个限制有什么解决方法吗 我真的很希望能够在内核函数中使用多态性 Thanks 罗伯特 克罗维拉评论中最重要的部分是 只需在设备上创建对象即可 所以记住这一点 我正在处理我有一
  • 估计 GPU 的 FLOPS 效率(CUDA 示例)

    在我看来 我并不完全理解 FLOPS 的概念 在CUDA SAMPLES中 有矩阵乘法示例 0 Simple matrixMul 在此示例中 每个矩阵乘法的 FLOP 浮点运算 数量通过以下公式计算 double flopsPerMatri
  • 使用非均匀节点优化 CUDA 内核插值

    原问题 我有以下内核使用非均匀节点执行插值 我想对其进行优化 global void interpolation cufftDoubleComplex Uj double points cufftDoubleComplex result i
  • 如何在 Linux 中分析 PyCuda 代码?

    我有一个简单的 经过测试的 pycuda 应用程序 正在尝试对其进行分析 我尝试过 NVidia 的 Compute Visual Profiler 它运行该程序 11 次 然后发出以下错误 NV Warning Ignoring the
  • C 中带括号和不带括号的循环处理方式不同吗?

    我在调试器中单步执行一些 C CUDA 代码 如下所示 for uint i threadIdx x i lt 8379 i 256 sum d PartialHistograms blockIdx x i HISTOGRAM64 BIN
  • CUDA错误:在python中使用并行时初始化错误

    我的代码使用 CUDA 但运行速度仍然很慢 因此 我将其更改为使用 python 中的多处理 pool map 并行运行 但我有CUDA ERROR initialization error 这是函数 def step M self ite
  • 为什么GK110有192个核心和4个扭曲?

    我想感受一下开普勒的架构 但这对我来说没有意义 如果一个 warp 有 32 个线程 其中 4 个被调度 执行 则意味着 128 个核心正在使用 64 个核心处于空闲状态 白皮书中提到了独立指令 那么64核是为这些指令保留的吗 如果是这样
  • 在新线程中调用支持 CUDA 的库

    我编写了一些代码并将其放入它自己的库中 该库使用 CUDA 在 GPU 上进行一些处理 我正在使用 Qt 构建 GUI 前端 作为加载 GUI 的一部分 我调用 CUresult res CUdevice dev CUcontext ctx
  • 如何将CUDA时钟周期转换为毫秒?

    我想用一些代码来测量时间within我的内核需要 我已经关注了这个问题 https stackoverflow com questions 11209228 timing different sections in cuda kernel连
  • cudaMallocManaged() 返回“不支持的操作”

    在 CUDA 6 0 中尝试托管内存给了我operation not supported打电话时cudaMallocManaged include cuda runtime h include
  • cuda 共享内存 - 结果不一致

    我正在尝试并行缩减以对 CUDA 中的数组求和 目前我传递一个数组来存储每个块中元素的总和 这是我的代码 include
  • 在linux上编译一个基本的OpenCV + Cuda程序

    我过去在linux上使用过opencv 但没有使用过cuda 几个月来我一直在与以下编译错误作斗争 在尝试了许多解决方案后 我放弃并使用 Windows 不过 我真的很想在 Linux 上工作 这是我用来编译 opencv gpu 网站上给
  • MPI+CUDA 与纯 MPI 相比有何优势?

    加速应用程序的常用方法是使用 MPI 或更高级别的库 例如在幕后使用 MPI 的 PETSc 并行化应用程序 然而 现在每个人似乎都对使用 CUDA 来并行化他们的应用程序或使用 MPI 和 CUDA 的混合来解决更雄心勃勃 更大的问题感兴
  • 如何优化这个 CUDA 内核

    我已经分析了我的模型 似乎该内核约占我总运行时间的 2 3 我一直在寻找优化它的建议 代码如下 global void calcFlux double concs double fluxes double dt int idx blockI
  • 如何在 Visual Studio 2010 中设置 CUDA 编译器标志?

    经过坚持不懈的得到error identifier atomicAdd is undefined 我找到了编译的解决方案 arch sm 20旗帜 但是如何在 VS 2010 中传递这个编译器标志呢 我已经尝试过如下Project gt P
  • CUDA线程执行顺序

    我有一个 CUDA 程序的以下代码 include
  • CUDA 估计 2D 网格数据的每块线程数和块数

    首先我要说的是 我已经仔细阅读了所有类似的问题 确定每个块的线程和每个网格的块 https stackoverflow com questions 4391162 cuda determining threads per block blo

随机推荐

  • DM6437 C64X+ EDMA 疑惑总结记录

    总结一下DM6437中的EDMA的使用出现的问题 方便以后再开发定位问题 1 EDMA Link 和 Chain的区别 link实现了DMA的自动重加载 非静态模式 需要两个param chain是不更新param set表 直接event
  • qt界面叠加视频OSD双层显示

    最终代码存放于 http download csdn net detail lzh445096 8849147 本人负责的是UI界面 提供给底层应用程序接口函数 此接口函数功能为向指定路径的文件中写入命令字符 应用程序去到该文件中读取到相应
  • 基于Protobuf协议的Dubbo与SpringBoot的结合

    文章目录 工程概况 父pom dubbo provider 通过proto3定义服务 打包发布服务 dubbo provider service实现服务 dubbo provider web提供服务 dubbo consumer dubbo
  • 依赖注入和控制反转的理解,写的太好了

    学习过Spring框架的人一定都会听过Spring的IoC 控制反转 DI 依赖注入 这两个概念 对于初学Spring的人来说 总觉得IoC DI这两个概念是模糊不清的 是很难理解的 今天和大家分享网上的一些技术大牛们对Spring框架的I
  • 互联网产品运作模式详解

    互联网产品运作模式详解 https www infoq cn article 3EVku39xVhJYs7ba9uk7 本文主要总结下移动互联网产品的市场运作模式 因为本身我是技术出身 对运作模式中的开发体系这 块相对熟悉 但是其他阶段也是
  • js: for in 循环对象

    var peopleObj man 2 2 2 woman 1 1 1 womanDoctor 100 100 100 for const prop in peopleObj if peopleObj hasOwnProperty prop
  • java将图片转为base64后出现的一些问题

    因为需要对接第三方接口 需要将图片转换为base64编码传参 手动转换base64使用postman完全是OK的 结果java中转换出来死活不行 p 将文件转成base64 字符串 p param path 文件路径 return thro
  • Linux下ps命令实现

    include
  • 思科实验-生成树协议STP

    生成树协议 英语 Spanning Tree Protocol STP 是一种工作在OSI网络模型中的第二层 数据链路层 的通信协议 基本应用是防止交换机冗余链路产生的环路 用于确保以太网中无环路的逻辑拓扑结构 从而避免了广播风暴 大量占用
  • vivado2021.1安装

    首先需要在官网注册一个账号 安装软件时需要使用 账号注册连接 xilink账号注册 vivado下载链接 xilink官网下载 使用官网下载需要注册账号 下载免费 vivado阿里云盘下载 vivado licence阿里云盘下载 官网下载
  • QStringLiteral(str)

    在看项目代码的时候 总会看到下面这种情况 QString str QStringLiteral 123rt QString用QStringLiteral str 来初始化 有点好奇 就查了下 记录一下 这是用QStringLiteral初始
  • Java:记录一下第一次面试经历(新希望六和)

    记录一下本菜鸡两个月前第一次面试新希望六合这家公司 那时的我很多都回答不上来 非常尴尬 不过这第一次面试经历也算是给足了我动力继续努力 记录一下这个第一次面试的题目 也算是记录一下那时候的我 做过什么样的项目 简单介绍一下你的项目 项目的整
  • 客户端请求的端口号是什么?

    我们知道服务器端是要指定和开放端口号的 比如 web 服务 http 请求的 80 https 的 443 端口 都要开放 否则无法请求成功 我们知道通信是由两端组成的 既然服务器需要指定端口 那么客户端呢 比方说我用 chrome 浏览器
  • 模型微调技术

    模型微调 一 迁移学习中的常见技巧 微调 fine tuning 1 1 概念 1 2 步骤 1 3 训练 1 4 实现 一 迁移学习中的常见技巧 微调 fine tuning 1 1 概念 将在大数据集上训练得到的weights作为特定任
  • java常用第三方类库

    几乎每个程序员都知道要 避免重复发明轮子 的道理 尽可能使用那些优秀的第三方框架或库 但当真正进入开发 时 我却经常发现他们有时并不知道那些轮子在哪里 最近 我在业余时间带几个年轻的程序员一起做了一个很小的商业项目 而在一起开发的过程中 我
  • Java使用Collections.reverse()反转一个List

    public class Demo public static void main String args ArrayList
  • 2023年CPU&GPU天梯图(最新版)

    在当今计算机世界 CPU GPU和显卡的性能成为了衡量计算机性能的重要指标 今天深入了解CPU GPU和显卡天梯图 首先 CPU作为计算机的大脑 负责处理各种任务 它的性能主要由核心数 主频和缓存大小决定 其中 核心数和主频决定了CPU的处
  • 我的2016--"狗血"

    偶然看到了CSDN的 我的2016 主题征文活动 突然感慨一番 今年又快结束了 而我这一年的经历 可以浓缩为两个字 狗血 然而 我能用上如此不羁的词汇 并未能掩盖我木讷的内心 这才真的是狗血 感觉像在梦游 走了好远的路 一睁开眼睛却还在原地
  • Qt5和Qt6在线安装的问题

    在线安装我的梯子怎么都安装不快 如果只是时间长也行啊 但是经常蹦出来一个 下载xxx无响应 你还得去盯着它 不然就给你自动退出了 着实有些烦人 得下载14个小时 有一个方法是更换镜像源 也就是 在cmd命令行如下执行 qt unified
  • 第一个CUDA程序-addVector

    本文主要通过对两个浮点数组中的数据进行相加 并将其结果放入第三个数组中 其算法分别在CPU GPU上分别执行 并比较了所需时间 强烈感受到GPU的并行计算能力 这里 每个数组的元素大小为30000000个 一 实现代码 cpp view p