C与CUDA混合编程的配置问题

2015-10-05 19:58 526人阅读 评论(2) 收藏 举报
分类:
CUDA(6)

目录(?)[+]

原文: http://blog.csdn.net/u012234115/article/details/34860273

在做项目集成的时候需要用到cpp和cuda文件联调,自己摸索了两种方式实现cpp和cu文件混合编译。

本文环境:

  • windows7 64位
  • VS2010
  • CUDA5.5
  • 英伟达显卡Tesla C1060

前言

因此不需要额外配置,不过为了保险起见,可以选择性地添加以下环境变量:
CUDA_BIN_PATH  %CUDA_PATH%\bin
CUDA_LIB_PATH  %CUDA_PATH%\lib\Win32
CUDA_SDK_BIN  %CUDA_SDK_PATH%\bin\Win32
CUDA_SDK_LIB  %CUDA_SDK_PATH%\common\lib\Win32
CUDA_SDK_PATH  C:\cuda\cudasdk\common

这时可以打开CUDA自带的sample运行一下,运行能通过才可以继续下面的内容————cpp和cuda联调。

方法一:先建立cuda工程,再添加cpp文件

1.打开vs2010,新建一个cuda项目,名称CudaCpp。

2.cuda默认建立的工程是如下,实现了两个一维向量的并行相加。kernel函数和执行函数还有main函数全都写在了一个cu文件里。

3.接下来在工程里添加一个空的cpp文件。将原来cu文件里main函数里的内容剪切到cpp文件main函数里。

为了让cpp能够调用cu文件里面的函数,在addWithCuda函数前加上extern "C" 关键字  (注意C大写,为什么addKernel不用加呢?因为cpp里面直接调用的是addWithCuda)

4.在cpp里也要加上addWithCuda函数的完整前向声明。下图就是工程的完整结构

5.可以在cpp里的main函数return之间加入getchar()防止运行后一闪就退出,加上system("pause")或者直接ctrl+F5也行。

运行结果:

下面贴出CudaCpp项目代码。

kernel.cu

[plain] view plaincopy
  1. #include "cuda_runtime.h"
  2. #include "device_launch_parameters.h"
  3. #include <stdio.h>
  4. __global__ void addKernel(int *c, const int *a, const int *b)
  5. {
  6. int i = threadIdx.x;
  7. c[i] = a[i] + b[i];
  8. }
  9. // Helper function for using CUDA to add vectors in parallel.
  10. extern "C"
  11. cudaError_t addWithCuda(int *c, const int *a, const int *b, unsigned int size)
  12. {
  13. int *dev_a = 0;
  14. int *dev_b = 0;
  15. int *dev_c = 0;
  16. cudaError_t cudaStatus;
  17. // Choose which GPU to run on, change this on a multi-GPU system.
  18. cudaStatus = cudaSetDevice(0);
  19. if (cudaStatus != cudaSuccess) {
  20. fprintf(stderr, "cudaSetDevice failed!  Do you have a CUDA-capable GPU installed?");
  21. goto Error;
  22. }
  23. // Allocate GPU buffers for three vectors (two input, one output)    .
  24. cudaStatus = cudaMalloc((void**)&dev_c, size * sizeof(int));
  25. if (cudaStatus != cudaSuccess) {
  26. fprintf(stderr, "cudaMalloc failed!");
  27. goto Error;
  28. }
  29. cudaStatus = cudaMalloc((void**)&dev_a, size * sizeof(int));
  30. if (cudaStatus != cudaSuccess) {
  31. fprintf(stderr, "cudaMalloc failed!");
  32. goto Error;
  33. }
  34. cudaStatus = cudaMalloc((void**)&dev_b, size * sizeof(int));
  35. if (cudaStatus != cudaSuccess) {
  36. fprintf(stderr, "cudaMalloc failed!");
  37. goto Error;
  38. }
  39. // Copy input vectors from host memory to GPU buffers.
  40. cudaStatus = cudaMemcpy(dev_a, a, size * sizeof(int), cudaMemcpyHostToDevice);
  41. if (cudaStatus != cudaSuccess) {
  42. fprintf(stderr, "cudaMemcpy failed!");
  43. goto Error;
  44. }
  45. cudaStatus = cudaMemcpy(dev_b, b, size * sizeof(int), cudaMemcpyHostToDevice);
  46. if (cudaStatus != cudaSuccess) {
  47. fprintf(stderr, "cudaMemcpy failed!");
  48. goto Error;
  49. }
  50. // Launch a kernel on the GPU with one thread for each element.
  51. addKernel<<<1, size>>>(dev_c, dev_a, dev_b);
  52. // Check for any errors launching the kernel
  53. cudaStatus = cudaGetLastError();
  54. if (cudaStatus != cudaSuccess) {
  55. fprintf(stderr, "addKernel launch failed: %s\n", cudaGetErrorString(cudaStatus));
  56. goto Error;
  57. }
  58. // cudaDeviceSynchronize waits for the kernel to finish, and returns
  59. // any errors encountered during the launch.
  60. cudaStatus = cudaDeviceSynchronize();
  61. if (cudaStatus != cudaSuccess) {
  62. fprintf(stderr, "cudaDeviceSynchronize returned error code %d after launching addKernel!\n", cudaStatus);
  63. goto Error;
  64. }
  65. // Copy output vector from GPU buffer to host memory.
  66. cudaStatus = cudaMemcpy(c, dev_c, size * sizeof(int), cudaMemcpyDeviceToHost);
  67. if (cudaStatus != cudaSuccess) {
  68. fprintf(stderr, "cudaMemcpy failed!");
  69. goto Error;
  70. }
  71. Error:
  72. cudaFree(dev_c);
  73. cudaFree(dev_a);
  74. cudaFree(dev_b);
  75. return cudaStatus;
  76. }

main.cpp

[cpp] view plaincopy
  1. #include <stdio.h>
  2. #include "cuda_runtime.h"
  3. #include "device_launch_parameters.h"
  4. extern "C"
  5. cudaError_t addWithCuda(int *c, const int *a, const int *b, unsigned int size);
  6. int main()
  7. {
  8. const int arraySize = 5;
  9. const int a[arraySize] = { 1, 2, 3, 4, 5 };
  10. const int b[arraySize] = { 10, 20, 30, 40, 50 };
  11. int c[arraySize] = { 0 };
  12. // Add vectors in parallel.
  13. cudaError_t cudaStatus = addWithCuda(c, a, b, arraySize);
  14. if (cudaStatus != cudaSuccess) {
  15. fprintf(stderr, "addWithCuda failed!");
  16. return 1;
  17. }
  18. printf("{1,2,3,4,5} + {10,20,30,40,50} = {%d,%d,%d,%d,%d}\n",
  19. c[0], c[1], c[2], c[3], c[4]);
  20. printf("cuda工程中调用cpp成功!\n");
  21. // cudaDeviceReset must be called before exiting in order for profiling and
  22. // tracing tools such as Nsight and Visual Profiler to show complete traces.
  23. cudaStatus = cudaDeviceReset();
  24. if (cudaStatus != cudaSuccess) {
  25. fprintf(stderr, "cudaDeviceReset failed!");
  26. return 1;
  27. }
  28. getchar(); //here we want the console to hold for a while
  29. return 0;
  30. }

方法二:先建立cpp工程,再添加cu文件

方法一由于是cuda工程是自动建立的,所以比较简单,不需要多少额外的配置。而在cpp工程里面添加cu就要复杂一些。为了简单起见,这里采用console程序讲解,至于MFC或者Direct3D程序同理。

1.建立一个空的win32控制台工程,名称CppCuda。

2.然后右键工程-->添加一个cu文件

3.将方法一中cu和cpp文件的代码分别拷贝到这个工程里来(做了少许修改,extern "C"关键字和某些头文件不要忘了加),工程结构如图:

这个时候编译是通不过的,需要作一些配置。

4.关键的一步,右键工程-->生成自定义 ,将对话框中CUDA5.5前面的勾打上。

这时点击 工程-->属性,会发现多了CUDA链接器这一项。

5.关键的一步,右键kernel.cu文件-->属性,在 常规-->项类型 里面选择CUDA C/C++(由于cu文件是由nvcc编译的,这里要修改编译链接属性)

6.工程-->属性-->链接器-->附加依赖项,加入cudart.lib

7.工具-->选项-->文本编辑器-->文件扩展名 添加cu \cuh两个文件扩展名

8.至此配置成功。运行一下:

9.为了更加确信cuda中的函数确实被调用,在main.cpp里面调用cuda函数的地方加入了一个断点。

单步执行一下。

可以看到程序跳到了cu文件里去执行了,说明cpp调用cuda函数成功。

贴上代码(其实跟方式一基本一样,没怎么改),工程CppCuda

kernel.cu

[plain] view plaincopy
  1. #include "cuda_runtime.h"
  2. #include "device_launch_parameters.h"
  3. #include <stdio.h>
  4. //cudaError_t addWithCuda(int *c, const int *a, const int *b, unsigned int size);
  5. __global__ void addKernel(int *c, const int *a, const int *b)
  6. {
  7. int i = threadIdx.x;
  8. c[i] = a[i] + b[i];
  9. }
  10. // Helper function for using CUDA to add vectors in parallel.
  11. extern "C"
  12. cudaError_t addWithCuda(int *c, const int *a, const int *b, unsigned int size)
  13. {
  14. int *dev_a = 0;
  15. int *dev_b = 0;
  16. int *dev_c = 0;
  17. cudaError_t cudaStatus;
  18. // Choose which GPU to run on, change this on a multi-GPU system.
  19. cudaStatus = cudaSetDevice(0);
  20. if (cudaStatus != cudaSuccess) {
  21. fprintf(stderr, "cudaSetDevice failed!  Do you have a CUDA-capable GPU installed?");
  22. goto Error;
  23. }
  24. // Allocate GPU buffers for three vectors (two input, one output)    .
  25. cudaStatus = cudaMalloc((void**)&dev_c, size * sizeof(int));
  26. if (cudaStatus != cudaSuccess) {
  27. fprintf(stderr, "cudaMalloc failed!");
  28. goto Error;
  29. }
  30. cudaStatus = cudaMalloc((void**)&dev_a, size * sizeof(int));
  31. if (cudaStatus != cudaSuccess) {
  32. fprintf(stderr, "cudaMalloc failed!");
  33. goto Error;
  34. }
  35. cudaStatus = cudaMalloc((void**)&dev_b, size * sizeof(int));
  36. if (cudaStatus != cudaSuccess) {
  37. fprintf(stderr, "cudaMalloc failed!");
  38. goto Error;
  39. }
  40. // Copy input vectors from host memory to GPU buffers.
  41. cudaStatus = cudaMemcpy(dev_a, a, size * sizeof(int), cudaMemcpyHostToDevice);
  42. if (cudaStatus != cudaSuccess) {
  43. fprintf(stderr, "cudaMemcpy failed!");
  44. goto Error;
  45. }
  46. cudaStatus = cudaMemcpy(dev_b, b, size * sizeof(int), cudaMemcpyHostToDevice);
  47. if (cudaStatus != cudaSuccess) {
  48. fprintf(stderr, "cudaMemcpy failed!");
  49. goto Error;
  50. }
  51. // Launch a kernel on the GPU with one thread for each element.
  52. addKernel<<<1, size>>>(dev_c, dev_a, dev_b);
  53. // Check for any errors launching the kernel
  54. cudaStatus = cudaGetLastError();
  55. if (cudaStatus != cudaSuccess) {
  56. fprintf(stderr, "addKernel launch failed: %s\n", cudaGetErrorString(cudaStatus));
  57. goto Error;
  58. }
  59. // cudaDeviceSynchronize waits for the kernel to finish, and returns
  60. // any errors encountered during the launch.
  61. cudaStatus = cudaDeviceSynchronize();
  62. if (cudaStatus != cudaSuccess) {
  63. fprintf(stderr, "cudaDeviceSynchronize returned error code %d after launching addKernel!\n", cudaStatus);
  64. goto Error;
  65. }
  66. // Copy output vector from GPU buffer to host memory.
  67. cudaStatus = cudaMemcpy(c, dev_c, size * sizeof(int), cudaMemcpyDeviceToHost);
  68. if (cudaStatus != cudaSuccess) {
  69. fprintf(stderr, "cudaMemcpy failed!");
  70. goto Error;
  71. }
  72. Error:
  73. cudaFree(dev_c);
  74. cudaFree(dev_a);
  75. cudaFree(dev_b);
  76. return cudaStatus;
  77. }

main.cpp

[cpp] view plaincopy
  1. #include <iostream>
  2. #include "cuda_runtime.h"
  3. #include "device_launch_parameters.h"
  4. using namespace std;
  5. extern "C"
  6. cudaError_t addWithCuda(int *c, const int *a, const int *b, unsigned int size);
  7. int main(int argc,char **argv)
  8. {
  9. const int arraySize = 5;
  10. const int a[arraySize] = { 1, 2, 3, 4, 5 };
  11. const int b[arraySize] = { 10, 20, 30, 40, 50 };
  12. int c[arraySize] = { 0 };
  13. // Add vectors in parallel.
  14. cudaError_t cudaStatus = addWithCuda(c, a, b, arraySize);
  15. if (cudaStatus != cudaSuccess) {
  16. fprintf(stderr, "addWithCuda failed!");
  17. return 1;
  18. }
  19. cout<<"{1,2,3,4,5} + {10,20,30,40,50} = {"<<c[0]<<','<<c[1]<<','<<c[2]<<','<<c[3]<<'}'<<endl;
  20. printf("cpp工程中调用cu成功!\n");
  21. // cudaDeviceReset must be called before exiting in order for profiling and
  22. // tracing tools such as Nsight and Visual Profiler to show complete traces.
  23. cudaStatus = cudaDeviceReset();
  24. if (cudaStatus != cudaSuccess) {
  25. fprintf(stderr, "cudaDeviceReset failed!");
  26. return 1;
  27. }
  28. system("pause"); //here we want the console to hold for a while
  29. return 0;
  30. }

注意有时候编译出问题,把  "device_launch_parameters.h" 这个头文件去掉就好了(去掉之后就不能调里面的函数或变量了),至于为什么,还不是很清楚。

C与CUDA混合编程的配置问题相关推荐

  1. Gtk与Cuda混合编程

    大家都知道,不同的编译器有不同的-L和-I,而在编译过程中要实现两种编译器的混合使用,利用Makefile是一个很好地解决方案,比如之前在mpi与cuda混合编程中讨论的那样,基于图形界面的GTK编程 ...

  2. c++和cuda混合编程记录(一)

    最近在用cuda将RT并行化. 很多人都说,最好使用c来写cuda,不要用类,尽量用struct代替.因为在cuda里面使用oo来套现在会有很多问题. 我也试过,确实很多问题,之前用cpp写的光线追踪 ...

  3. Java与Cuda混合编程

    基本上和Java与C语言混合编程(链接)相同,就是在生成动态库的编译过程不同. 首先编写一个名为Main.java的文件,内容如下: class NativeMethod{public native ...

  4. Mpi与Cuda混合编程(Makefile)

    需要建立一个.c的MPI程序和一个.cu的CUDA程序,MPI程序中调用CUDA中的函数来完成并行与GPU的混合编程,我查询了很多资料和博客,最终得出结论,还是Google比较强大,百度什么的还是搜不 ...

  5. CUDA、SU、MPI和Madagascar混合编程的Makefile文件配置

    本人从事地震勘探的科研工作,在Ubuntu系统中用CUDA.SU.MPI和Madagascar做C语言的混合编程.多语言混合编程,关键之处在于Makefile文件的配置.在此给出一个简单的示例,供大家 ...

  6. CUDA C编程接口技术分析

    CUDA C编程接口技术分析 编程接口 CUDA C为熟悉C编程语言的用户提供了一个简单的路径,可以方便地编写程序供设备执行. 它由C语言的最小扩展集和运行库组成. 核心语言扩展已经引入:cuda c ...

  7. CUDA C++编程接口:编译

    CUDA C++编程接口:编译 一.概述 CUDA C++为熟悉C++编程语言的用户提供了一个简单的路径,以方便地编写程序以执行该设备. 它由一组最小的扩展到C++语言和运行库. 在编程模型中引入了核 ...

  8. matlab两个多项式相除,C++和MATLAB混合编程求解多项式系数(矩阵相除)

    摘要:MATLAB对于矩阵处理是非常高效的,而C++对于矩阵操作是非常麻烦的,因而可以采用C++与MATLAB混合编程求解矩阵问题. 主要思路就是,在MATLAB中编写函数脚本并使用C++编译为dll ...

  9. matlab求解多项式系数,C++和MATLAB混合编程求解多项式系数(矩阵相除)

    摘要:MATLAB对于矩阵处理是非常高效的,而C++对于矩阵操作是非常麻烦的,因而可以采用C++与MATLAB混合编程求解矩阵问题. 主要思路就是,在MATLAB中编写函数脚本并使用C++编译为dll ...

最新文章

  1. [转] 中国的车祸为什么多?一个”海归”的亲身体验(转)
  2. Cpp / shared_ptr
  3. 软件测试(四)之 PrintPrimes
  4. java快捷键查看目录,java取得快捷方式指向的路径
  5. Java(1-15)
  6. 03. Java NIO Channel 通道
  7. android 透明主题 crash,Android 8.0 的填坑(透明的activity崩溃)
  8. html给图片设置编剧,漫画简明编剧教程【4】如何设计角色
  9. 全球首发!惯性导航导论(剑桥大学)第八部分
  10. cas修改界面html,为REST API配置的CAS将v1 / ticket重定向到登录HTML
  11. 软件测试面试,秋招你准备好了吗?(内附答案)
  12. ABBYY PDF Transformer+功能概述
  13. 最长回文字串--动态规划
  14. matlab在数学教学,Matlab在数学函数教学中的应用
  15. (LINPACK)HPL测试成功步骤整理
  16. Tegra environment
  17. 30分钟写一个聊天板
  18. 如何用计算机作图并求斜率,简单斜率分析以及作图
  19. android电脑手柄游戏平台,玩转PC、安卓TV、Stam平台等多平台的游戏手柄——北通斯巴达2...
  20. ---- 招聘之操作系统原理 ----

热门文章

  1. vmware virtualization software
  2. 人终究要活出自己对于这个世界的看法和自己的处事方式,并且由内而外的生成自信
  3. 项目用的几种机型参数调查
  4. 什么时候必须使用UI相机? 多个相机的作用原理?
  5. VMware ESXi 6.7安装配置
  6. tp剩余未验证内容-7
  7. UML学习总结(1)——UML学习入门
  8. 散度、旋度与 Laplacian
  9. 务实云计算培训:帮您顺利走好云之旅
  10. 三大主流开源工作流引擎技术分析与市场预测