Matlab cuda代码在单独编译模式下的mex链接

Matlab cuda代码在单独编译模式下的mex链接,matlab,cuda,mex,Matlab,Cuda,Mex,我试图在linux下的MatlabMex中使用CUDA代码。在“全程序编译”模式下,它对我来说很好。我在Nsight中执行以下两个步骤: (1) 将“-fPIC”作为编译器选项添加到每个.cpp或.cu文件中,然后分别编译它们,每个生成一个.o文件 (2) 将链接器命令设置为“mex”并添加“-cxx”以指示所有.o输入文件的类型都是cpp文件,并添加cuda的库路径。还可以添加一个包含mexFunction条目的cpp文件作为附加输入 该方法运行良好,生成的mex文件在MATLAB下运行良好。

我试图在linux下的MatlabMex中使用CUDA代码。在“全程序编译”模式下,它对我来说很好。我在Nsight中执行以下两个步骤:

(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
template<typename ValueType>
void func(ValueType x);
有趣的是,链接器没有将.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下自动链接到mex可执行文件中,而Nsight可以在“整个程序编译”模式下运行。我的做法如下:

(1) 从包含mexFunction项的cpp文件生成中排除。使用命令“mex-c”手动编译它

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

(3) 链接将失败,因为它找不到主函数。我们没有它,因为我们使用mexFunction,它被排除在外。这没关系,我就把它放在那里

(4) 按照下面文章中的方法手动将.o文件dlink到设备对象文件中

例如,如果步骤(2)生成a.o和b.o,那么我们在这里执行

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),因为它涉及两个命令,我不知道如何将它们放入。如果你知道怎么做,请告诉我。谢谢

首先,应该可以设置Night以使用自定义生成文件,而不是自动生成它。看

一旦我们有了一个定制的Makefile,就可以自动化(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
包含
mxFunction
,但
helper.c
不包含


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

首先,应该可以设置Night来使用自定义生成文件,而不是自动生成它。看

一旦我们有了一个定制的Makefile,就可以自动化(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
包含
mxFunction
,但
helper.c
不包含

编辑:您可以在自动编译系统中实现相同的效果。右键单击每个源文件并选择属性,您将获得一个窗口,可以在其中为该单个文件添加一些编译选项
#define ValueType float
#include "f.inc"
#undef ValueType

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

// Add other types you want.