【问题标题】:compile cuda code with relocatable device code through python distutils (for python c extension)通过 python distutils 使用可重定位设备代码编译 cuda 代码(用于 python c 扩展)
【发布时间】:2020-02-07 17:59:24
【问题描述】:

我有一些使用协作组的 cuda 代码,因此需要 -rdc=true 标志才能使用 nvcc 进行编译。我想从 python 调用 cuda 代码,所以我正在编写一个带有 python c 扩展的 python 接口。

因为我包含了 cuda 代码,所以我必须调整我的 setup.py,如:Can python distutils compile CUDA code? 中所述

这会编译和安装,但是一旦我在 python 中导入我的代码,它就会出现段错误。删除 -rdc=true 标志使一切正常,但迫使我从 cuda 内核中删除任何协作组代码(或在编译期间得到“cudaCGGetIntrinsicHandle unresolved”错误)。

我有什么办法可以进一步调整我的 setup.py 以使其正常工作?或者,是否有其他方法可以编译允许 cuda 代码(打开 rdc 标志)的 c 扩展?

【问题讨论】:

  • 显而易见的事情是检查回溯并查看导致段错误的原因。如果没有一些关于什么是破坏的想法,很难说要改变什么

标签: python c++ cuda


【解决方案1】:

我想我已经找到了答案。如果您使用 nvcc 生成可重定位设备代码,则 nvcc 需要链接目标文件以便正确处理设备代码链接,或者您需要通过在所有具有可重定位设备代码的目标文件上运行 nvcc 来生成单独的目标文件,并带有 ' --device-link' 标志。然后可以将这个额外的目标文件包含在外部链接器的所有其他目标文件中。

我通过在源文件列表的末尾添加一个虚拟的“link.cu”文件来调整 Can python distutils compile CUDA code? 的设置。我还为 cuda 设备链接步骤添加了 cudadevrt 库和另一组编译器选项:

ext = Extension('mypythonextension',
                sources=['python_wrapper.cpp', 'file_with_cuda_code.cu', 'link.cu'],
                library_dirs=[CUDA['lib64']],
                libraries=['cudart', 'cudadevrt'],
                runtime_library_dirs=[CUDA['lib64']],

                extra_compile_args={'gcc': [],
                                    'nvcc': ['-arch=sm_70', '-rdc=true', '--compiler-options', "'-fPIC'"],
                                    'nvcclink': ['-arch=sm_70', '--device-link', '--compiler-options', "'-fPIC'"]
                                    },
                include_dirs = [numpy_include, CUDA['include'], 'src'])

然后,适应编译器调用的函数通过以下方式获取它:

def customize_compiler_for_nvcc(self):
    self.src_extensions.append('.cu')

    # track all the object files generated with cuda device code
    self.cuda_object_files = []

    super = self._compile

    def _compile(obj, src, ext, cc_args, extra_postargs, pp_opts):
        # generate a special object file that will contain linked in
        # relocatable device code
        if src == 'link.cu':
            self.set_executable('compiler_so', CUDA['nvcc'])
            postargs = extra_postargs['nvcclink']
            cc_args = self.cuda_object_files[1:]
            src = self.cuda_object_files[0]
        elif os.path.splitext(src)[1] == '.cu':
            self.set_executable('compiler_so', CUDA['nvcc'])
            postargs = extra_postargs['nvcc']
            self.cuda_object_files.append(obj)
        else:
            postargs = extra_postargs['gcc']
        super(obj, src, ext, cc_args, postargs, pp_opts)
        self.compiler_so = default_compiler_so

    self._compile = _compile

由于我缺乏 distutils 知识,该解决方案感觉有点骇人听闻,但它似乎有效。 :)

【讨论】:

    猜你喜欢
    • 2012-04-19
    • 2016-11-02
    • 1970-01-01
    • 2013-06-24
    • 2014-08-07
    • 2018-10-13
    • 2012-03-14
    • 2011-12-22
    • 2011-03-13
    相关资源
    最近更新 更多