gpt4 book ai didi

matlab - 在单独的编译模式下将cuda代码进行mex链接

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:10:55 25 4
gpt4 key购买 nike

我正在尝试在linux下的matlab mex中使用cuda代码。使用“整个程序编译”模式,对我很有用。我在nsight内执行以下两个步骤:
(1)将“-fpic”作为编译器选项添加到每个.cpp或.cu文件中,然后分别编译它们,每个文件生成一个.o文件。
(2)将链接器命令设置为“mex”并添加“-cxx”,以指示所有.o输入文件的类型都是cpp文件,并添加cuda的库路径。还可以添加一个cpp文件,其中包含mexfunction条目作为附加输入。
该方法运行良好,生成的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),我想这就是为什么我不能让它像在“整个程序编译”模式下那样工作的原因。所以我尝试了以下几点:
(一)按照职务开始时的相同方式编制。
(2)保留nsight提供的链接命令,但更改为使用“-shared”选项,以便链接器生成lib文件。
(3)通过输入lib文件和另一个包含mexfunction条目的cpp文件来调用mex。
这样,mex编译工作,并生成一个mex可执行文件作为输出。但是,在Matlab下运行生成的MEX可执行文件会立即产生分割错误并使Matlab崩溃。
我不确定这种连接方式是否会引起任何问题。更奇怪的是,我发现mex链接步骤似乎完成得很简单,甚至没有检查可执行文件的完整性,因为即使我错过了mex function将使用的某个函数的.cpp文件,它仍然可以编译。
编辑:
我想知道如何手动链接到一个可以在Matlab下正确运行的MEX可执行文件中,但是我还没有想好如何在nsight下自动链接,我可以在“整个程序编译”模式下。我的方法是:
(1)从生成包含mexfunction项的cpp文件中排除。用命令“mex-c”手动编译它。
(2)将“-fpic”作为编译器选项添加到每个rest.cpp或.cu文件中,然后分别编译它们,每个文件生成一个.o文件。
(3)找不到主功能,链接失败。我们没有它,因为我们使用mexfunction,它被排除在外。这没关系,我就把它留在那儿。
(4)按照下面的方法手动将.O文件链接到设备对象文件中
cuda shared library linking: undefined reference to cudaRegisterLinkedBinary
例如,如果步骤(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),是因为它涉及两个命令,我不知道如何将它们放入其中。如果你知道怎么做,请告诉我。谢谢!

最佳答案

好吧,我找到了解决办法。下面是在nsight中使用“单独编译模式”编译mex程序的完整步骤:
创建CUDA项目。
在项目级别中,更改以下项的生成选项:
在项目级“nvcc compiler”的编译器选项中打开-fPIC
-dlink -Xcompiler '-fPIC'添加到链接器“nvcc linker”的“专家设置”“命令行模式”
在“build artifact”->“artifact extension”中添加字母o,因为在最后一步中,我们将通过-dlink使输出成为一个.o文件。
在“后期构建步骤”中添加mex -cxx -o path_to_mex_bin/mex_bin_filename ./*.o ./src/*.o -lcudadevrt(添加其他必要的lib)
更新:在我的实际项目中,我将最后一步移到了Matlab中的一个.m文件中,因为否则,如果我在运行Mex程序时这样做,可能会导致Matlab崩溃。
对于需要用mex编译的文件,请为每个文件更改以下生成选项:
在工具链编辑器中将编译器更改为GCC C++ Compiler
返回GCC C++ Compiler的编译器设置并将命令更改为mex
将命令行模式更改为${COMMAND} -c -outdir "src" ${INPUTS}
几个附加说明:
(1)必须向MEX编译器隐藏CUDA特定的详细信息(例如内核函数和对内核函数的调用)。所以它们应该放在.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可执行文件或普通可执行文件,从而允许在nsight下不使用matlab进行调试。下面是在nsight下建立多个目标的技巧: Building multiple binaries within one Eclipse project

关于matlab - 在单独的编译模式下将cuda代码进行mex链接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14600405/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com