VS里面关于.cpp文件与.cu文件混合编译问题---不要在.cpp文件声明核函数(__device__()和global__())
原文出处:点击打开链接
#############################################################
不要在.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_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工程,再添加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
- #include "cuda_runtime.h"
- #include "device_launch_parameters.h"
- #include <stdio.h>
- __global__ void addKernel(int *c, const int *a, const int *b)
- {
- int i = threadIdx.x;
- c[i] = a[i] + b[i];
- }
- // Helper function for using CUDA to add vectors in parallel.
- extern "C"
- 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;
- // Choose which GPU to run on, change this on a multi-GPU system.
- cudaStatus = cudaSetDevice(0);
- if (cudaStatus != cudaSuccess) {
- fprintf(stderr, "cudaSetDevice failed! Do you have a CUDA-capable GPU installed?");
- goto Error;
- }
- // Allocate GPU buffers for three vectors (two input, one output) .
- 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;
- }
- // Copy input vectors from host memory to GPU buffers.
- 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;
- }
- // Launch a kernel on the GPU with one thread for each element.
- addKernel<<<1, size>>>(dev_c, dev_a, dev_b);
- // Check for any errors launching the kernel
- cudaStatus = cudaGetLastError();
- if (cudaStatus != cudaSuccess) {
- fprintf(stderr, "addKernel launch failed: %s\n", cudaGetErrorString(cudaStatus));
- goto Error;
- }
- // cudaDeviceSynchronize waits for the kernel to finish, and returns
- // 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;
- }
- // Copy output vector from GPU buffer to host memory.
- 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;
- }
main.cpp
- #include <stdio.h>
- #include "cuda_runtime.h"
- #include "device_launch_parameters.h"
- extern "C"
- cudaError_t addWithCuda(int *c, const int *a, const int *b, unsigned int size);
- 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 };
- // Add vectors in parallel.
- 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]);
- printf("cuda工程中调用cpp成功!\n");
- // cudaDeviceReset must be called before exiting in order for profiling and
- // tracing tools such as Nsight and Visual Profiler to show complete traces.
- cudaStatus = cudaDeviceReset();
- if (cudaStatus != cudaSuccess) {
- fprintf(stderr, "cudaDeviceReset failed!");
- return 1;
- }
- getchar(); //here we want the console to hold for a while
- return 0;
- }
方法二:先建立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
- #include "cuda_runtime.h"
- #include "device_launch_parameters.h"
- #include <stdio.h>
- //cudaError_t addWithCuda(int *c, const int *a, const int *b, unsigned int size);
- __global__ void addKernel(int *c, const int *a, const int *b)
- {
- int i = threadIdx.x;
- c[i] = a[i] + b[i];
- }
- // Helper function for using CUDA to add vectors in parallel.
- extern "C"
- 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;
- // Choose which GPU to run on, change this on a multi-GPU system.
- cudaStatus = cudaSetDevice(0);
- if (cudaStatus != cudaSuccess) {
- fprintf(stderr, "cudaSetDevice failed! Do you have a CUDA-capable GPU installed?");
- goto Error;
- }
- // Allocate GPU buffers for three vectors (two input, one output) .
- 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;
- }
- // Copy input vectors from host memory to GPU buffers.
- 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;
- }
- // Launch a kernel on the GPU with one thread for each element.
- addKernel<<<1, size>>>(dev_c, dev_a, dev_b);
- // Check for any errors launching the kernel
- cudaStatus = cudaGetLastError();
- if (cudaStatus != cudaSuccess) {
- fprintf(stderr, "addKernel launch failed: %s\n", cudaGetErrorString(cudaStatus));
- goto Error;
- }
- // cudaDeviceSynchronize waits for the kernel to finish, and returns
- // 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;
- }
- // Copy output vector from GPU buffer to host memory.
- 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;
- }
main.cpp
- #include <iostream>
- #include "cuda_runtime.h"
- #include "device_launch_parameters.h"
- using namespace std;
- extern "C"
- cudaError_t addWithCuda(int *c, const int *a, const int *b, unsigned int size);
- int main(int argc,char **argv)
- {
- 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 };
- // Add vectors in parallel.
- cudaError_t cudaStatus = addWithCuda(c, a, b, arraySize);
- if (cudaStatus != cudaSuccess) {
- fprintf(stderr, "addWithCuda failed!");
- return 1;
- }
- cout<<"{1,2,3,4,5} + {10,20,30,40,50} = {"<<c[0]<<','<<c[1]<<','<<c[2]<<','<<c[3]<<'}'<<endl;
- printf("cpp工程中调用cu成功!\n");
- // cudaDeviceReset must be called before exiting in order for profiling and
- // tracing tools such as Nsight and Visual Profiler to show complete traces.
- cudaStatus = cudaDeviceReset();
- if (cudaStatus != cudaSuccess) {
- fprintf(stderr, "cudaDeviceReset failed!");
- return 1;
- }
- system("pause"); //here we want the console to hold for a while
- return 0;
- }
注意有时候编译出问题,把 "device_launch_parameters.h" 这个头文件去掉就好了(去掉之后就不能调里面的函数或变量了),至于为什么,还不是很清楚。
以后将cu文件加入到任何MFC,qt,D3D或者OpenGL等C++工程中步骤都是类似的。
VS里面关于.cpp文件与.cu文件混合编译问题---不要在.cpp文件声明核函数(__device__()和global__())相关推荐
- r在服务器如何输出文件,在Rstudio服务器中编译Rmd时,.tex文件保存在哪里
这可能听起来像一个愚蠢的问题,但我想知道当我从Rmd文件编译pdf文档时,保存的.tex文件在哪里,使用RStudio服务器. 我加了keep_tex选项,所以RMD的头看起来是这样的:在Rstudi ...
- makefile obj文件路径_Makefile一问:如何修改.o输出文件的输出路径 Linux/Unix社区 / 程序开......
我在Linux下编成时,用Makefile文件生成的.o文件老是跟我的源文件在同一个目录下,搞得我用TAB键之余还得先再敲.c再TAB,为什么要多敲两次键盘?如果我把所有生成的.o文件放比如./obj ...
- andriod 自编译,打包生成apk文件--------------------cocos2d-x 3.0正式版本(7.7)
一.搭建搭建环境 1. 安装JDK 和 Android SDK 2. 配置环境变量 D:\android-sdk-windows\tools C:\Program Files\Java\jdk1.6. ...
- linux编译cpp文件命令,Jsoncpp Linux 下编译为 .a 文件
1 下载 jsoncpp 路径如下: https://github.com/open-source-parsers/jsoncpp 2. 解压文件 unzip jsoncpp-master.zip 3 ...
- android.mk 冒号,android学习-ndk-build(androidstudio编译cocos2d-x库的cpp为so文件的解释)
本文不作为ndk初学使用,只是对cpp等c++文件编译成so文件的过程中,参数含义,及ndk配置的解释.使用的技术比较旧. androidStudio使用gradle调用ndk-build工具编译c+ ...
- vs2013编译caffe的io.cpp文件错误,open close无法识别
vs2013编译caffe的io.cpp文件错误,open和close无法识别, 解决方法: 将下列代码放在io.cpp的前面 #ifdef _MSC_VER #define open _open # ...
- 习题 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 ...
- 手机 download .cu .log_手机清理内存,这些英文文件哪些是可以删除的?看完就知道...
对于智能手机,我们除了一些日常生活中的必须使用功能之外,很多时候,都没有太过于仔细的却挖掘他它一些功能,例如手机清理内存,我们最多就是用手机管家清理一下,或者是将一些缓存的视频照片删除,其实这样清理手 ...
- GCC 同时编译多个 C/C++ 文件
以下这些操作都可以共用一条 gcc 指令: 将多个 C/C++ 源文件加工为汇编文件或者目标文件: 将多个 C/C++ 源文件或者预处理文件加工为汇编文件或者目标文件: 将多个 C/C++ 源文件.预 ...
最新文章
- python读取图片并且显示
- js随机跳转域名_【教程】无需域名和服务器搭建属于自己的导航页!!!
- 【软件工程】技术规格说明书
- 4g内存 堆内存分配多少_我需要多少内存
- c#扩展方法奇思妙用性能篇一:扩展方法性能初测
- leetcode165. 比较版本号 超级重要的细节
- SQL事务处理实验报告
- 服务器接口文档详细 接口文档模板 规范 完整
- android ipv6 谷歌,Ipv6使用google服务的DNS
- 交通银行一直显示服务器繁忙,交通银行信用卡人工服务一直繁忙
- 三十九、如何单独发布jar包
- 想改变Facebook? 先改变扎克伯格!
- 翼支付个人账单查询接口
- 苹果手机7P ios14 nfc怎么复制门禁卡
- 利用DirectShow开发C#版的MP3播放器(二)
- Destoon增加内容页的浏览历史记录
- java如何给数组初始化?
- 网络空间安全是指什么/网络空间安全是怎么产生的
- 8.3K Star,这才是我们苦苦寻找的PDF阅读器。。。
- 求1到100之间的奇数之和、偶数之积。
热门文章
- 剑指 Offer II 110. 所有路径
- 10-4 用select进行调度
- sql判断字段不为null_什么是NULL值
- 如何获取web视频数据流的传输?小姐姐的视频都被我爬下来了,这谁顶得住
- asp.net web开发步骤_如何在Windows上做Python开发?微软出了官方教程
- c语言编辑学生信息录入的程序,c语言编的学生信息管理系统小程序!!有不足的请指出,谢谢!!...
- html条纹填充色,HTML5/Canvas 上传图片的彩色斑马条纹遮罩效果
- php 8.0 jit,PHP 8.0 正式版发布,性能提升 10%
- java 调用 spring,java中使用redis和spring中调用redis
- 50欧姆线设计 高频pcb_高频电路布线的应对方法有哪些?