现在的位置: 首页 > 综合 > 正文

CUDA在Windows下的软件开发环境搭建

2018年12月11日 ⁄ 综合 ⁄ 共 8396字 ⁄ 字号 评论关闭

http://www.cnblogs.com/yaoyuanzhi/archive/2010/11/13/1876215.html

CUDA在Windows下的软件开发环境搭建 

本文我们以Visual Studio 2005 为例演示CUDA的安装以及软件开发环境搭建,以及CUDA与MFC联调的实现。

1.cuda安装包

CUDA是免费使用的,各种操作系统下的CUDA安装包均可以在http://www.nvidia.cn/object/cuda_get_cn.html上免费下载。CUDA提供3个安装包,分别是: Driver, Toolkit和SDK。SDK包括许多例子程序和函数库。Toolkit包括CUDA的基本工具。安装时按照顺序,先安装Driver,再Toolkit,最后SDK。

CUDA toolkit

安装后在NVIDIA_CUDA_toolkit安装目录下出现6个文件夹,分别是:

Bin :     工具程序和动态链接库

Doc :     相关文档

Include : header头文件包

Lib :     程序库

Open64 :  基于open64的CUDA compiler

Src :     部分原始代码

安装过程中toolkit自动设定了3个环境变量:CUDA_BIN_PATH、CUDA_INC_PATH和CUDA_LIB_PATH分别对应工具程序库、头文件库和程序库,预设路径为当前安装文件夹下的bin、include 和lib三个文件夹。

CUDA SDK

SDK可以根据需要选择安装(推荐安装,因为SDK中的许多例子程序和函数库非常有用。

CUDA Display

对于没有安装NV显卡的计算机,不需要安装Display安装包,程序也可以在模拟模式下运行。

2.在Visual Studio2005中使用CUDA

    CUDA的主要工具是nvcc,它会执行所需要的程序,将CUDA程序编译并执行。本文将介绍在windows环境下,基于VS 2005IDE环境下的几种配置cuda nvcc的方法。

2.1 NV自带的修改模板方法

    在CUDA SDK安装目录下的project目录下新建文件夹,命名为想要建立的工程名字,比如test1。并在project文件夹下找到SDK自带的template文件夹,将template文件夹下所有的文件copy到test1下。

    将copy到test1文件夹下的所有文件文件名中的template改为test(也即是自己的工程文件名字)。test.sln与test.vcproj是vs 8系列的工程文件,test_vc7.sln与test_vc7.vcproj是vs 7系列的工程文件,可以根据自己Visual Studio的版本选择要更改的工程文件,其它两个可以删除。在Visual Studio C++ 2005 Express中,删除test_vc7.sln与test_vc7.vcproj即可。

将*.cu、*.sln和*.vcproj用记事本等文字编辑软件打开,使用查找替换功能将以上文件中所有的template改为test。

使用*.sln文件打开整个工程,可以任意更改代码,编译运行。

修改输出文件路径(可选,如不改变,可执行文件输出到上两级目录下的bin目录中),如使用了CUDA SDK中的动态链接库,将相应的动态链接库拷贝到可执行文件的同一目录下。

  

    总结:这种方法是NV公司为windows下使用vs编译cuda提供的标准方法(参见\SDK\doc\CUDA_SDK_release_notes_windows.txt), 使用公司提供的模板更改为自己想要建立的工程,也可以参照以上方法,在SDK Project库中的找到与自己想建立工程相近的其它工程做更改。

2.2 在Win32项目中建立.cu文件

    首先建立一个C++的win32的控制台应用程序empty project,并添加一个新的源文件,此处以main.cu为例。

P1.建立一个win32 project

设定为empty project

P3.建立一个CUDA程序专用的main.cu文件

在solution explorer 中main.cu上右键单击,选择property。在打开的对话框中选择General,确定Tool的选项是Custom Build Tool。

确认Tool选项为Custom build Tool。

选择Custom Bulid Step,在Command Line中分别设定模式参数。这里要分几种编译方式来设定命令行参数。

 (1)、Release 模式:"$(CUDA_BIN_PATH)\nvcc.exe" -ccbin "$(VCInstallDir)bin" -c -DWIN32 -D_CONSOLE -D_MBCS -Xcompiler /EHsc,/W3,/nologo,/Wp64,/O2,/Zi,/MT -I"$(CUDA_INC_PATH)" -o $(ConfigurationName)\$(InputName).obj $(InputFileName)

 (2)、Debug 模式:"$(CUDA_BIN_PATH)\nvcc.exe" -ccbin "$(VCInstallDir)bin" -c -D_DEBUG -DWIN32 -D_CONSOLE -D_MBCS -Xcompiler /EHsc,/W3,/nologo,/Wp64,/Od,/Zi,/RTC1,/MTd -I"$(CUDA_INC_PATH)" -o $(ConfigurationName)\$(InputName).obj $(InputFileName)

    如果计算机中没有安装NV显卡,使用模拟模式,需增加两个额外的设定。新建两个模式EmuRelease和EmuDebug。

P6.新建模式(1)

P6.新建模式(2)

        对新建立的EmuRelease和EmuDebug的Command Line分别设定为:

(1)、EmuRelease 模式:"$(CUDA_BIN_PATH)\nvcc.exe" -ccbin "$(VCInstallDir)bin" -deviceemu -c -DWIN32 -D_CONSOLE -D_MBCS -Xcompiler /EHsc,/W3,/nologo,/Wp64,/O2,/Zi,/MT -I"$(CUDA_INC_PATH)" -o $(ConfigurationName)\$(InputName).obj $(InputFileName)

(2)、EmuDebug 模式:"$(CUDA_BIN_PATH)\nvcc.exe" -ccbin "$(VCInstallDir)bin" -deviceemu -c -D_DEBUG -DWIN32 -D_CONSOLE -D_MBCS -Xcompiler /EHsc,/W3,/nologo,/Wp64,/Od,/Zi,/RTC1,/MTd -I"$(CUDA_INC_PATH)" -o $(ConfigurationName)\$(InputName).obj $(InputFileName)

3.1.4、对所有的设定模式,均在 Custom Build Step 的 Outputs 中加入 $(ConfigurationName)\$(InputName).obj。

P7.设定Outputs

右键单击project,选择Property,再选择Linker,对所有模式修改以下设定:

(1)、General/Enable Incremental Linking:No

(2)、General/Additional Library Directories:$(CUDA_LIB_PATH)

(3)、Input/Additional Dependencies:cudart.lib

P8.设定Linker参数(1)

P9.设定Linker参数(2)

设置头文件路径Tools -> Options,弹出以下对话框

将右边的下拉框选择Include Files,点击添加按钮,将C:\Program Files\NVIDIA Corporation\NVIDIA CUDA SDK\common\inc选入到头文件搜索路径中。

选择链接库文件路径

同上库头文件路径选择,将右边下拉框选择Library File,选择路径C:\Program Files\NVIDIA Corporation\NVIDIA CUDA SDK\common\lib。

完成,可以编写cuda程序,并直接编译执行了(编译方式于C++相同)

总结:这种方法既不需要借助模板,也不需要使用第三方的软件。但是操作相当复杂,而且仅对配置的单个project有效。如果重新建立一个project又要重新配置一遍。

需要注意的是,当需要使用CUDA SDK中的动态链接库(以dll为后缀)时,将动态链接库和生成的可执行文件放在同一个路径下。

如果是driver API,需要添加”cuda.lib cudart.lib”,头文件#include ,#include。

2.3 使用CUDA_VS_Wizard插件

    下载CUDA_VS_Wizard插件并安装。

    将CUDA安装目录下的bin和CUDA SDK安装目录下的bin\win32文件夹下的四个文件夹(Debug, EmuDebug, Release, EmuRelease)的路径全部加入环境变量中的path变量中。

    使用vc直接建立工程。在工程选项里选择CUDAWinApp。

   

如果是在模拟模式下运行,需要在解决方案中右键属性,在Configuration Properities 中将Configuration 设置为Emu模式。

模拟模式设置(1)

模拟模式设置(2)。

总结:这种方法虽然使用了第三方的工具,但只需要配置一次即可,而且配置简单,以后每次建立cuda程序都可以直接生成。如果是建立预定义头文件的工程,则建立的cuda程序,会自带一个sample.cu,可以选择在sample.cu的基础上更改或删除sample.cu重新建立.cu文件。如果是建立空工程则没有。建立方法.cu文件的方法是建立.cpp文件或.txt文件改名为.cu文件即可。推荐使用。

2.4 语法高亮设置。

找到CUDA SDK安装目录下doc\syntax_highlighting\自带的文件usertypt.dat,将其copy到Microsoft Visual Studio 安装目录的\Common7\IDE下。

在Visual Studio中做以下设置: 在Tools-> Options ->Text Editor-> File Extension中添加cu。编辑方式Microsoft Visual C++。

   

P16.设置高亮

重新启动Visual Studio,完成高亮设置。

??

3.配置生成规则。将SDK目录下C/common目录下的cuda,rules拷贝到VS安装目录下的VC\VCProjectDefaults子目录下。建立一个 Win32工程,并在项目上右击,选择custombuildrules,在CUDA build rule前打勾。在工程中新建一个.cu文件,右击属性后查看自定义生成规则是否已经是CUDA build rule。

3. CUDA在MFC中的联调方法实例

3.1 SDK中程序的编译

         例如我们的SDK安装路径“C:\Program Files\NVIDIA Corporation\NVIDIA CUDA SDK\projects\deviceQuery”中可以找到deviceQuery的工程文件。

         当我们把这个文件夹拷贝到其他目录下时,会出现找不到头文件的错误,如“找不到cutil.h”。为什么会出现这种情况呢?我们注意到在deviceQuery中对其的引用#include <cutil.h>,是在系统目录下的。这个系统目录在C:\Program Files\NVIDIA Corporation\NVIDIA CUDA SDK\common\inc中可以找到cutil.h头文件。

         通过查看deviceQuery.cu的属性,通过观察“命令行”:

"$(CUDA_BIN_PATH)\nvcc.exe" -ccbin "$(VCInstallDir)bin" -c -D_DEBUG -DWIN32 -D_CONSOLE -D_MBCS -Xcompiler /EHsc,/W3,/nologo,/Wp64,/Od,/Zi,/RTC1,/MTd -I"$(CUDA_INC_PATH)" -I./ -Ihttp://www.cnblogs.com/common/inc -o $(ConfigurationName)\deviceQuery.obj deviceQuery.cu

注意红色下划线部分,带便往上退两个文件夹,然后进入commom文件夹中的inc文件夹。再比较之前的两个路径,这正好是deciceQuery.sin文件到cutil.h的一个访问的过程。

 

         当我们将工程文件拷贝到新的目录下时,这样的一个访问方式必然会失效。于是我们需要做如下的一些设置。

1.  首先我们需要将C:\Program Files\NVIDIA Corporation\NVIDIA CUDA SDK\bin\win32文件目录下的四个文件夹分别添加到环境变量里。

 

具体的操作方法是:”我的电脑” ->属性->高级->环境变量PATH,注意路径都是全路径,每个变量间用“;”分隔。

 

2.  注意到这里面的系统变量NVSDKCUDA_ROOT为C:\Program Files\NVIDIA Corporation\NVIDIA CUDA SDK。

 

我们在转移了工程文件目录后,只需要将命令行进行修改。即将之前的红线部分作如下修改:

"$(CUDA_BIN_PATH)\nvcc.exe" -ccbin "$(VCInstallDir)bin" -c -D_DEBUG -DWIN32 -D_CONSOLE -D_MBCS -Xcompiler /EHsc,/W3,/nologo,/Wp64,/Od,/Zi,/RTC1,/MTd -I"$(CUDA_INC_PATH)" -I./ -I"$(NVSDKCUDA_ROOT)/common/inc" -o $(ConfigurationName)\deviceQuery.obj deviceQuery.cu

3.  此外我们还需要将“项目属性”的“链接器”做对应的修改。然后该程序即可正常编译运行。

 

3.2 MFC中应用CUDA程序

本章建立一个MFC工程,然后在该工程中添加对cu文件中CUDA程序的调用。本章还可参考SDK中的程序示例cppIntegration。

3.2.1 配置VisualStudio环境配置准备工作

语法高亮:将d:\programming\cuda\sdk\doc\syntax_highlighting\visual_studio_8里面的usertype.dat文件copy到Microsoft Visual Studio 8\Common7\IDE目录下面(如果已经存在,就追加到原来的后面)。

设置VS2005环境(因为本程序将不仅仅是在cu文件中使用CUDA函数了,其中还包括在cpp文件中使用,所以需要包括这些库)

进入Tools|Options|Projects and Solutions|VC++Directories 添加: 

Include files:

d:\programming\cuda\toolkit\include

d:\programming\cuda\sdk\common\inc 

Library files:

d:\programming\cuda\toolkit\lib

d:\programming\cuda\sdk\common\lib

Source files:d:\programming\cuda\sdk\common\src    

文本编辑器设置:进入VC++ Project Settings:C/C++ File extensions:添加*.cu,在Text editor-File extension:添加cu 对应editor到Microsoft VC++ editor。    

Visual Assist X设置(如果需要安装的话):关闭已经所有打开的Visual studio,安装VA,之后进入注册表编辑器:HKEY_CURRENT_USER\Software\Whole Tomato\VANet8 找到右边的ExtSource项,将其值添加.cu;.cuh;之后关闭,再次打开VS2005即可。) 

3.2.2 创建全局函数和头文件

         首先我们在头文件和资源文件中建立全局函数以供调用:

         这里的testcuda函数采用extern关键字声明C语言扩展。

 

我们在查看类视图的时候就可以看到该全局函数:

 

3.2.3 创建CUDA代码

为了标示清楚,我们首先创建了一个名为CUDA的筛选器,然后在该筛选器中分别创建名为first.cu和first_kernel.cu的两个源代码文件。然后其中添加代码如下:

#include "stdio.h"

#include "cutil.h"

#include "first_kernel.cu"

extern "C" void runtest(float *source,int datalen,float *result)

{

    int count;

    cudaGetDeviceCount(&count);

    if(count == 0) {

        fprintf(stderr, "There is no device.\n");

         *result=-1;

    }

    int i;

    for(i = 0; i < count; i++) {

        cudaDeviceProp prop;

        if(cudaGetDeviceProperties(&prop, i) == cudaSuccess) {

            if(prop.major >= 1) {

                break;

            }

        }

    }

    if(i == count) {

        fprintf(stderr, "There is no device supporting CUDA 1.x.\n");

         *result=-1;

    }

     float * d_source,*d_result;

     cudaMalloc((void**)&d_source,datalen*sizeof(float));

     cudaMalloc((void**)&d_result,sizeof(float));

     cudaMemcpy(d_source,source,datalen*sizeof(float),cudaMemcpyHostToDevice);

     kernel<<<1,256,0>>>(d_source,datalen,d_result);

    

     cudaMemcpy(result,d_result,sizeof(float),cudaMemcpyDeviceToHost);

     cudaFree(d_source);

     cudaFree(d_result);

}

以及在first_kernel.cu中添加的内核函数(即并行部分):

#ifndef _FIRST_KERNEL_H_

#define _FIRST_KERNEL_H_

__global__ void kernel(float *source,int len,float *result)

{

     int i;

     float sum;

     sum=0;

     for(i=0;i<len;i++)

         sum+=*(source+i);

        

     *result=sum;

}

#endif

3.2.3 修改链接器设置

首先是first.cu的属性设置:

将“常规”中的工具一项设为“自定义生成工具”。

然后在命令行中参考3.1中的设置方式。这里需要注意的是“附加依赖项”为first_kernel.cu.

 

 

而在first_kernel.cu中的属性设置,我们需要将这个存放内核函数的文件“从生成中排除”。

 

         最后是设置项目的属性,仍旧参照3.1在“项目属性”的“链接器”的属性中作一些改动。

 

         在“项目属性”的“链接器”的“输入”中加入附加依赖项库文件cudart.lib

 

         最后便可以编译运行程序了^_^!

抱歉!评论已关闭.