原文出处:点击打开链接

#############################################################

不要在.cpp文件声明核函数,否则会报错,具体可以参考下面两个链接:

http://blog.csdn.net/lingerlanlan/article/details/25063331?utm_source=tuicool

https://stackoverflow.com/questions/16550031/cuda-device-and-global-error-expected-constructor-destructor-or-type

############################################################

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

本文环境:

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

前言

装好CUDA 5.5 sdk后,默认会自动添加好系统环境变量。
因此不需要额外配置,不过为了保险起见,可以选择性地添加以下环境变量:
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 print?
  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 print?
  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 print?
  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 print?
  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"  这个头文件去掉就好了(去掉之后就不能调里面的函数或变量了),至于为什么,还不是很清楚。

以后将cu文件加入到任何MFC,qt,D3D或者OpenGL等C++工程中步骤都是类似的。

VS里面关于.cpp文件与.cu文件混合编译问题---不要在.cpp文件声明核函数(__device__()和global__())相关推荐

  1. r在服务器如何输出文件,在Rstudio服务器中编译Rmd时,.tex文件保存在哪里

    这可能听起来像一个愚蠢的问题,但我想知道当我从Rmd文件编译pdf文档时,保存的.tex文件在哪里,使用RStudio服务器. 我加了keep_tex选项,所以RMD的头看起来是这样的:在Rstudi ...

  2. makefile obj文件路径_Makefile一问:如何修改.o输出文件的输出路径 Linux/Unix社区 / 程序开......

    我在Linux下编成时,用Makefile文件生成的.o文件老是跟我的源文件在同一个目录下,搞得我用TAB键之余还得先再敲.c再TAB,为什么要多敲两次键盘?如果我把所有生成的.o文件放比如./obj ...

  3. andriod 自编译,打包生成apk文件--------------------cocos2d-x 3.0正式版本(7.7)

    一.搭建搭建环境 1. 安装JDK 和 Android SDK 2. 配置环境变量 D:\android-sdk-windows\tools C:\Program Files\Java\jdk1.6. ...

  4. linux编译cpp文件命令,Jsoncpp Linux 下编译为 .a 文件

    1 下载 jsoncpp 路径如下: https://github.com/open-source-parsers/jsoncpp 2. 解压文件 unzip jsoncpp-master.zip 3 ...

  5. android.mk 冒号,android学习-ndk-build(androidstudio编译cocos2d-x库的cpp为so文件的解释)

    本文不作为ndk初学使用,只是对cpp等c++文件编译成so文件的过程中,参数含义,及ndk配置的解释.使用的技术比较旧. androidStudio使用gradle调用ndk-build工具编译c+ ...

  6. vs2013编译caffe的io.cpp文件错误,open close无法识别

    vs2013编译caffe的io.cpp文件错误,open和close无法识别, 解决方法: 将下列代码放在io.cpp的前面 #ifdef _MSC_VER #define open _open # ...

  7. 习题 8.5 将本章的例8.4改写为一个多文件的程序:1.将类定义放在头文件arraymax.h中;2.将成员函数定义放在源文件arraymax.cpp中;3.主函数放在源文件file1.cpp中。

    C++程序设计(第三版) 谭浩强 习题8.5 个人设计 习题 8.5 将本章的例8.4改写为一个多文件的程序: 1.将类定义放在头文件arraymax.h中: 2.将成员函数定义放在源文件arraym ...

  8. 手机 download .cu .log_手机清理内存,这些英文文件哪些是可以删除的?看完就知道...

    对于智能手机,我们除了一些日常生活中的必须使用功能之外,很多时候,都没有太过于仔细的却挖掘他它一些功能,例如手机清理内存,我们最多就是用手机管家清理一下,或者是将一些缓存的视频照片删除,其实这样清理手 ...

  9. GCC 同时编译多个 C/C++ 文件

    以下这些操作都可以共用一条 gcc 指令: 将多个 C/C++ 源文件加工为汇编文件或者目标文件: 将多个 C/C++ 源文件或者预处理文件加工为汇编文件或者目标文件: 将多个 C/C++ 源文件.预 ...

最新文章

  1. python读取图片并且显示
  2. js随机跳转域名_【教程】无需域名和服务器搭建属于自己的导航页!!!
  3. 【软件工程】技术规格说明书
  4. 4g内存 堆内存分配多少_我需要多少内存
  5. c#扩展方法奇思妙用性能篇一:扩展方法性能初测
  6. leetcode165. 比较版本号 超级重要的细节
  7. SQL事务处理实验报告
  8. 服务器接口文档详细 接口文档模板 规范 完整
  9. android ipv6 谷歌,Ipv6使用google服务的DNS
  10. 交通银行一直显示服务器繁忙,交通银行信用卡人工服务一直繁忙
  11. 三十九、如何单独发布jar包
  12. 想改变Facebook? 先改变扎克伯格!
  13. 翼支付个人账单查询接口
  14. 苹果手机7P ios14 nfc怎么复制门禁卡
  15. 利用DirectShow开发C#版的MP3播放器(二)
  16. Destoon增加内容页的浏览历史记录
  17. java如何给数组初始化?
  18. 网络空间安全是指什么/网络空间安全是怎么产生的
  19. 8.3K Star,这才是我们苦苦寻找的PDF阅读器。。。
  20. 求1到100之间的奇数之和、偶数之积。

热门文章

  1. 剑指 Offer II 110. 所有路径
  2. 10-4 用select进行调度
  3. sql判断字段不为null_什么是NULL值
  4. 如何获取web视频数据流的传输?小姐姐的视频都被我爬下来了,这谁顶得住
  5. asp.net web开发步骤_如何在Windows上做Python开发?微软出了官方教程
  6. c语言编辑学生信息录入的程序,c语言编的学生信息管理系统小程序!!有不足的请指出,谢谢!!...
  7. html条纹填充色,HTML5/Canvas 上传图片的彩色斑马条纹遮罩效果
  8. php 8.0 jit,PHP 8.0 正式版发布,性能提升 10%
  9. java 调用 spring,java中使用redis和spring中调用redis
  10. 50欧姆线设计 高频pcb_高频电路布线的应对方法有哪些?