2014-01-19 75 views
2

我试图在linux下使用MATLAB mex下的CUDA代码。使用“整个程序编译”模式,它对我有用。我在Nsight中采取以下两个步骤:mex链接的独立编译模式下的cuda代码

(1)将“-fPIC”作为编译器选项添加到每个.cpp或.cu文件,然后分别编译它们,每个文件生成一个.o文件。 (2)将链接器命令设置为“mex”并添加“-cxx”以表示所有.o输入文件的类型都是cpp文件,并为cuda添加库路径。还要添加一个包含mexFunction条目的cpp文件作为附加输入。

这工作良好,导致mex文件在MATLAB下运行良好。之后,当我需要使用动态并行时,我必须切换到Nsight中的“单独编译模式”。我尝试了上面的同样的事情,但链接器产生了很多错误的引用,这是我无法解决的。

然后我检查了“独立编译”模式的编译和链接步骤。我对它正在做的事情感到困惑。看起来,Nsight为每个.cpp或.cu文件执行两个编译步骤,并生成.o文件和.d文件。就像这样:

/usr/local/cuda-5.5/bin/nvcc -O3 -gencode arch=compute_35,code=sm_35 -odir "src" -M -o "src/tn_matrix.d" "../src/tn_matrix.cu" 
/usr/local/cuda-5.5/bin/nvcc --device-c -O3 -gencode arch=compute_35,code=compute_35 -gencode arch=compute_35,code=sm_35 -x cu -o "src/tn_matrix.o" "../src/tn_matrix.cu" 

的连接命令是这样的:

/usr/local/cuda-5.5/bin/nvcc --cudart static --relocatable-device-code=true -gencode arch=compute_35,code=compute_35 -gencode arch=compute_35,code=sm_35 -link -o "test7" ./src/cu_base.o ./src/exp_bp_wsj_dev_mex.o ./src/tn_main.o ./src/tn_matlab_helper.o ./src/tn_matrix.o ./src/tn_matrix_lib_dev.o ./src/tn_matrix_lib_host.o ./src/tn_model_wsj_dev.o ./src/tn_model_wsj_host.o ./src/tn_utility.o -lcudadevrt -lmx -lcusparse -lcurand -lcublas 

有趣的是链接器不走.D文件作为输入。所以我不确定它是如何处理这些文件的,以及如何在链接时使用“mex”命令处理它们?

另一个问题是,链接阶段有很多我不明白的选项(--cudart static --relocatable-device-code = true),我想这是我无法使它工作的原因在“整个程序编译”模式下。所以我尝试了以下内容:

(1)以与帖子开头相同的方式进行编译。 (2)保留Nsight提供的链接命令,但改为使用“-shared”选项,以便链接器生成一个lib文件。 (3)通过输入lib文件和另一个包含mexFunction条目的cpp文件调用mex。

这种方式mex编译工作,它产生一个mex可执行文件作为输出。但是,在MATLAB下运行生成的mex可执行文件会立即产生分段错误并导致MATLAB崩溃。

我不确定这种连接方式是否会导致任何问题。更奇怪的是,我发现mex链接步骤似乎没有检查可执行文件的完整性即可完成,因为即使我错过了mexFunction将使用的某个函数的.cpp文件,它仍然会编译。

编辑:

我想出如何手动链接成一个可执行MEX可MATLAB下运行正常,但我还没有想出怎么做,下Nsight自动,这是我可以在“全程序编译“模式。这是我的方法:

(1)排除构建包含mexFunction条目的cpp文件。用命令“mex -c”手动编译它。

(2)将“-fPIC”作为编译器选项添加到其余的.cpp或.cu文件中,然后分别编译它们,每个文件生成一个.o文件。

(3)链接将失败,因为它无法找到主要功能。我们没有它,因为我们使用mexFunction,它被排除在外。这并不重要,我只是把它留在那里。

(4)按照在下面的柱的方法手动DLINK .o文件到一个设备对象文件

cuda shared library linking: undefined reference to cudaRegisterLinkedBinary

例如,如果步骤(2)产生A0和B0,这里我们做

nvcc -gencode arch=compute_35,code=sm_35 -Xcompiler '-fPIC' -dlink a.o b.o -o mex_dev.o -lcudadevrt 

请注意,这里输出文件mex_dev.o应该不存在,否则上述命令将失败。 (5)使用mex命令链接步骤(2)和步骤(4)中生成的所有.o文件,并提供所有必需的库。

这可以工作并生成可运行的mex可执行文件。我无法在Nsight中自动执行步骤(1)的原因是,如果我将编译命令更改为“mex”,Nsight也将使用此命令生成依赖文件(问题文本中提到的.d文件)。我之所以不能在Nsight中自动执行步骤(4)和步骤(5),是因为它涉及两条命令,我不知道如何将它们放入。请让我知道如果您知道如何执行这些操作。谢谢!

回答

2

好的,我想出了解决方案。以下是在Nsight中用“单独编译模式”编译mex程序的完整步骤:

  1. 创建一个cuda项目。
  2. 在项目层面上,更改以下构建选项:在项目级“NVCC编译”的编译器选项上-fPIC

    • 开关。在我们正在最后一步神器扩展“因为由-dlink -
    • 添加-dlink -Xcompiler '-fPIC'到“链接器”,“专家设置”的“命令行模式NVCC链接”
    • 添加字母o以“打造神器”>”输出一个.o文件。
    • 添加mex -cxx -o path_to_mex_bin/mex_bin_filename ./*.o ./src/*.o -lcudadevrt到“后生成步骤”,(加上其他必要的库)

    更新:在我的实际项目中,我提出的最后一步,在MATLAB一个.m文件,否则如果我去做了,而我的mex程序正在运行,可能会导致MATLAB崩溃。

  3. 对于文件需要与墨西哥进行编译,改变这些构建选项为他们每个人:

    • 变化的工具链编辑器,编译器,以GCC C++ Compiler
    • 回的GCC C++ Compiler编译器设置和改变命令mex
    • 更改命令线图案以${COMMAND} -c -outdir "src" ${INPUTS}

几个附加注释:

(1)Cuda的具体细节(如内核函数和对内核函数的调用)必须隐藏在mex编译器中。所以他们应该放在.cu文件而不是头文件中。这是一个将涉及cuda细节的模板放入.cu文件的技巧。

在头文件(例如,f.h),你只放了函数的声明是这样的:

template<typename ValueType> 
void func(ValueType x); 

添加一个名为f.inc一个新的文件,其中包含定义

template<> 
void func(ValueType x) { 
    // possible kernel launches which should be hidden from mex 
} 

在源代码文件(例如,f.cu)中,您将此

#define ValueType float 
#include "f.inc" 
#undef ValueType 

#define ValueType double 
#include "f.inc" 
#undef ValueType 

// Add other types you want. 

这个技巧可以很容易地推广到模板类来隐藏细节。

(2)mex的具体细节也应该从cuda源文件中隐藏,因为mex.h会改变一些系统函数的定义,如printf。所以包含“mex.h”的文件不应该出现在可能包含在cuda源文件中的头文件中。 (3)在包含条目mexFunction的mex源代码文件中,可以使用编译器宏MATLAB_MEX_FILE来选择性地编译代码段。通过这种方式,可以将源代码文件编译为mex可执行文件或通常可执行文件,从而允许在没有matlab的情况下在Nsight下进行调试。以下是在Nsight下构建多个目标的技巧:Building multiple binaries within one Eclipse project

1

首先,应该可以设置Night使用自定义Makefile而不是自动生成它。见Setting Nsight to run with existing Makefile project。 (1),(4)和(5)自动化。自定义Makefile的优点在于您确切知道将发生哪些编译命令。

的精简版的例子:

all: mx.mexa64 

mx.mexa64: mx.o 
    mex -o mx.mexa64 mx.o -L/usr/local/cuda/lib64 -lcudart -lcudadevrt 

mx.o: mxfunc.o helper.o 
    nvcc -arch=sm_35 -Xcompiler -fPIC -o mx.o -dlink helper.o mxfunc.o -lcudadevrt 

mxfunc.o: mxfunc.c 
    mex -c -o mxfunc.o mxfunc.c 

helper.o: helper.c 
    nvcc -arch=sm_35 -Xcompiler -fPIC -c -o helper.o helper.c 

clean: 
    rm -fv mx.mexa64 *.o 

...其中mxfunc.c包含mxFunctionhelper.c没有。

编辑:您可能能够在自动编译系统中实现相同的效果。右键单击每个源文件并选择属性,然后您将看到一个窗口,您可以在该窗口中为该单个文件添加一些编译选项。对于链接选项,打开项目的属性。做一些实验,并注意控制台中显示的实际编译命令。根据我的经验,自定义选项有时会以奇怪的方式与自动系统进行交互。如果这种方法对您来说太麻烦了,我建议您制作一个自定义的Makefile;这样,至少我们不会被意想不到的副作用所吸引。

+0

感谢您的解决方案!不过,我不想使用自定义makefile解决方案,因为我喜欢Eclipse提供的自动化管理工具。你知道如果我有一个自定义的makefile,那么我可以稍后将它转换为Eclipse项目吗? 对于mex,它有一个命令行版本,它和matlab里面调用的一样。 – shaoyl85

+0

^是的,我已经更新了示例以使用mex的命令行版本,这绝对看起来更好。我还会添加一些关于如何修改自动编译系统的说明...... –

+0

我做了一些Google搜索,但是我没有找到将自定义Makefile转换为托管项目的方法。我认为这是因为,像其他命令行工具一样,Makefile提供了很大的灵活性。 –