Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

如何实现 cuda 的 device-link? #433

Closed
OpportunityLiu opened this issue Jun 2, 2019 · 34 comments
Closed

如何实现 cuda 的 device-link? #433

OpportunityLiu opened this issue Jun 2, 2019 · 34 comments

Comments

@OpportunityLiu
Copy link
Member

OpportunityLiu commented Jun 2, 2019

类似这种流程

cxx:    main.cpp                                       -> main.o
cxx:    lib.cpp                                        -> lib.o
cu:     kernel1.cu                                     -> kernal1.o
cu:     kernal2.cu                                     -> kernal2.o
cu-ld:  kernal1.o, kernal2.o                           -> gpucode.o
ld:     main.o, lib.o, kernal1.o, kernal2.o, gpucode.o -> main

ref: https://devblogs.nvidia.com/separate-compilation-linking-cuda-device-code/

@waruqi
Copy link
Member

waruqi commented Jun 2, 2019

可以加个 cuda.device_link 的rule规则,不过目前rule和target还不支持 link 阶段的 定制,这块等我想想,改进下rule后,在处理这个好了。。

@waruqi waruqi added this to the v2.2.7 milestone Jun 2, 2019
@OpportunityLiu
Copy link
Member Author

感觉既然有了构建工具,这个流程才是更正确的,而且这样 cu-ld 和 ld 分开配置也更灵活,可以考虑搞成cuda 工程的默认构建流程

@waruqi
Copy link
Member

waruqi commented Jun 2, 2019

目前除了纯c/++项目,其他项目的构建过程 就是通过rule来分离的,像qt项目的设置 qt.application rule就是qt项目的默认构建

cuda的项目,目前是跟c/c++默认的构建行为一致,所以我暂时没加rule,如果觉得cuda的项目 行为差异比较大,或者需要一些特殊处理,可以像qt/wdk等项目一样,默认就通过rule来分离,标示为cuda项目

例如:

target("test")
    add_rules("cuda.console")
    add_files("src/*.cu")

通过内置的:cuda.console, cuda.static, cuda.shared 来表示 cuda 系列的项目基础项目类型。

内置对cuda项目的各种默认构建规则处理,包括内置的device-link处理逻辑。

@waruqi
Copy link
Member

waruqi commented Jun 6, 2019

rule/target的 on_link, before_link, after_link 阶段我也开放出来了,下一步我打算吧cuda项目的构建规则完全独立出来,像qt/sdk项目一样

目前规划可以创建以下三类项目,以后如果还有其他cuda项目类型,也可基于此扩展:

  • cuda.console
  • cuda.static
  • cuda.shared

项目描述:

target("test")
    add_rules("cuda.console")
    add_files("src/*.cu")

然后在里面我会内置各种跟cuda相关的构建rule,包括link阶段会默认改用 device-link

包括之前 includes里面 cuda.add_codegende 那个 rule 我也会内置在 cuda.console 这三大项目规则里面去生效

add_cucodegens 里面 就不必重复 apply cuda.add_codegende 这个规则了

这块我下周来弄下好了。。

@waruqi
Copy link
Member

waruqi commented Jun 10, 2019

这块我初步改好了,你可以到cuda分支下试试。。

目前的处理方式:

  1. 新增cuda项目构建规则,独立处理cuda相关代码的构建逻辑
  2. 扩展语言配置,可内建支持一些rule,因此像cuda这种,只需要检测到 *.cu 相关源文件,就会内置add_rules("cuda")到对应的target,既做到构建规则的隔离,有不影响之前兼容性,对用户完全无感知。
  3. add_cugencodes这个设置确实比较常用,我也内置到cuda的相关api里面去了,不用额外includes进来了
  4. 新增 add_culdflags() 接口设置,仅用于设置 cuda/device-link相关的链接选项
  5. 默认最终链接还是使用ld/gcc/clang,不用nvcc了。。
  6. 默认采用device-link来构建

因此,目前cuda项目的xmake.lua配置如下:

target("test")
    set_kind("binary")
    add_includedirs("inc")
    add_files("src/*.cu")
    add_cugencodes("compute_60,sm_60")
--    add_culdflags("-gencode arch=compute_60,code=sm_60")

跟现有之前的配置方式完全兼容,但是内部对cuda的构建处理,已经完全隔离到独立的cuda rule下面去了,也方便日后灵活扩展改进构建规则。

[  0%]: ccache compiling.release src/main.cu
/usr/local/bin/ccache /Developer/NVIDIA/CUDA-10.1/bin/nvcc -c -Iinc -gencode arch=compute_60,code=sm_60 -m64 -Xcompiler -arch -Xcompiler x86_64 -I/Developer/NVIDIA/CUDA-10.1/include -ccbin /usr/bin/clang -o build/.objs/testc/macosx/x86_64/release/src/main.cu.o src/main.cu
[100%]: devlinking.release testc_gpucode.cu.o
/Developer/NVIDIA/CUDA-10.1/bin/nvcc -o build/.objs/testc/macosx/x86_64/release/.cuda/devlink/testc_gpucode.cu.o build/.objs/testc/macosx/x86_64/release/src/main.cu.o -gencode arch=compute_60,code=sm_60 -dlink
[100%]: linking.release testc
"/usr/bin/xcrun -sdk macosx clang++" -o build/macosx/x86_64/release/testc build/.objs/testc/macosx/x86_64/release/src/main.cu.o build/.objs/testc/macosx/x86_64/release/.cuda/devlink/testc_gpucode.cu.o -L/Developer/NVIDIA/CUDA-10.1/lib -Xlinker -rpath -Xlinker /Developer/NVIDIA/CUDA-10.1/lib -lcudart -arch x86_64 -mmacosx-version-min=10.14 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk -stdlib=libc++ -lz

现在编译过程中,会额外增加一部device-link过程:

[100%]: devlinking.release testc_gpucode.cu.o

最终的link过程,还是走 gcc/clang,所以cu-ld和ld是独立的,可分别设置对应的device-link/link的链接工具。

@waruqi
Copy link
Member

waruqi commented Jun 10, 2019

之前的cuda.console方式,我想了下,就不采用了,因为这个跟Qt的规则还是有些不同的,qt/wdk的项目,比较独立,可算是一个完整的应用程序,而cuda的项目,可附加到其他项目类型上去。。

比如: qt + cuda 的规则同时生效也是有可能的,因此cuda.console的方式就不太合理了,我统一成 cuda rule了,即使在qt项目下,两种规则也可同时生效,比如:add_rules("qt.application", "cuda")

当然,xmake探测到 *.cu 就会自动应用cuda规则,所以,只需要 add_rules("qt.application") + *.cu 即可创建 带cuda的 其他项目程序

@waruqi
Copy link
Member

waruqi commented Jun 10, 2019

@OpportunityLiu 你先试试吧,我目前只在mac下测过,其他平台暂时没环境测试,如果测试ok,我就更新下文档,merge过去了。

@OpportunityLiu
Copy link
Member Author

OpportunityLiu commented Jun 10, 2019

图片
win上这个path貌似不太对

加上 add_linkdirs("C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.1\\lib\\x64") 暂时可用,但是应该是需要改一下

@waruqi
Copy link
Member

waruqi commented Jun 10, 2019

哦,方便的话,能否可以帮忙修下,

target:add("linkdirs", path.join(cuda_dir, "lib"))
target:add("rpathdirs", path.join(cuda_dir, "lib"))

或者等晚上有时间 我再改下。

@OpportunityLiu
Copy link
Member Author

OpportunityLiu commented Jun 10, 2019

还有add_linksadd_linkdirs没有对device link生效,建议直接一股脑加上,不用再分什么add_culinksadd_culinkdirs

需要

The device linker has the ability to read the static host library formats (.a on Linux and Mac OS X, .lib on Windows). It ignores any dynamic (.so or .dll) libraries.

@waruqi
Copy link
Member

waruqi commented Jun 10, 2019

对这块不是很了解,device link 也需要 链接库么?我看之前你给的文档里面 并没有提到,所以我暂时只对 最终的link上 加上links/linkdirs。

@OpportunityLiu
Copy link
Member Author

一般来讲不会有人导出gpu函数到库里,不过我看给nvcc加的 -l 会传给nvlink,所以还是加上吧。
这个对编译速度应该影响不大吧。

@OpportunityLiu
Copy link
Member Author

然后32为我这里测不了
图片
不过devlink那步的时候我也没看到你有给 -m64

@waruqi
Copy link
Member

waruqi commented Jun 10, 2019

一般来讲不会有人导出gpu函数到库里,不过我看给nvcc加的 -l 会传给nvlink,所以还是加上吧。
这个对编译速度应该影响不大吧。

对速度没啥影响,只要确认devlink确实有可能需要处理link/linkdirs,那就加上好了。

在这里加上 target.links/ target.linkdirs等devlink需要的设置就行了

, gpucode =
{
"target.culdflags"
, "option.culdflags"
}

@waruqi
Copy link
Member

waruqi commented Jun 10, 2019

然后32为我这里测不了
图片
不过devlink那步的时候我也没看到你有给 -m64

devlink阶段,我还不确定是否需要区分32/64bits,所以暂时没加。。如果需要 也可以在rule/after_load里面加上

这边win暂时没环境,也测不了,这边mac默认也是64bits,所以测下来倒是ok,回头可以试试32bits的版本。。

@OpportunityLiu
Copy link
Member Author

图片
大概率也是不行的

@OpportunityLiu
Copy link
Member Author

图片
然后你这libpath在linux也没搞对啊?难道mac上就一个版本的库?

@OpportunityLiu
Copy link
Member Author

图片
感觉x86已经被抛弃很久了。。。

@OpportunityLiu
Copy link
Member Author

OpportunityLiu commented Jun 10, 2019

CUDA 7.0 的时候抛弃的。。。

@OpportunityLiu
Copy link
Member Author

然后 host link 的时候是不是应该把几个cuda的库加上
Win: cudadevrt.lib
Linux: -lcudadevrt -lrt -lpthread -ldl
要链接devlink生成的.o,这几个应该是必须的

@OpportunityLiu
Copy link
Member Author

还有APPVEYOR的配置
图片
这个是不是改成 -branch master,反正只是用来编译新的xmake,用master版的应该就可以,不然这持续集成全炸

@OpportunityLiu
Copy link
Member Author

devlink的时候漏了 ccbin,直接传 cu-cxx 应该可以

@OpportunityLiu
Copy link
Member Author

target:add("links", "cudart")

这个有点问题,默认链接应该是 “cudart_static”,指定 -cudart shared 以后链接的才是 “cudart”

@OpportunityLiu
Copy link
Member Author

OpportunityLiu commented Jun 10, 2019

还有一些写在这边了 #449

@OpportunityLiu
Copy link
Member Author

devlink阶段,我还不确定是否需要区分32/64bits,所以暂时没加。。如果需要 也可以在rule/after_load里面加上

肯定是需要的,不管nvcc编译cu还是devicelink,本质都是生成了一个.c文件,交给ccbin去编译的

@OpportunityLiu
Copy link
Member Author

OpportunityLiu commented Jun 10, 2019

图片

研究了下发现默认的编译选项确实不需要 device-link,生成的GPU code也无法跨编译单元调用,只有在编译的时候加上 -rdc=true 以后才需要 device-link

不过nvcc的默认流程还时常直接调用device-link的,所以这样编译速度也并不会变慢就是了

This works because if the device linker does not see any relocatable code it does not do anything.
https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#using-separate-compilation-in-cuda

@OpportunityLiu
Copy link
Member Author

另外,生成静态库是不需要device-link的,可以看到,直接调用了lib

C:\Users\lzy\Documents\Source\OpportunityLiu\PowerFlow\PowerFlow>nvcc -o build\\.objs\\Test\\windows\\x64\\release\\.cuda\\devlink\\Test_gpucode.cu.obj build\\.objs\\Test\\windows\\x64\\release\\src\\pf\\nr_common_cood.cu.obj build\\.objs\\Test\\windows\\x64\\release\\src\\pf\\nr_common.cu.obj build\\.objs\\Test\\windows\\x64\\release\\src\\pf\\device\\fdpf.cu.obj build\\.objs\\Test\\windows\\x64\\release\\src\\pf\\device\\nr.cu.obj build\\.objs\\Test\\windows\\x64\\release\\src\\math\\dev_solver.cu.obj -gencode arch=compute_50,code=sm_50 --lib -dryrun
#$ _SPACE_=
#$ _CUDART_=cudart
#$ _HERE_=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\bin
#$ _THERE_=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\bin
#$ _TARGET_SIZE_=
#$ _TARGET_DIR_=
#$ _TARGET_SIZE_=64
#$ _WIN_PLATFORM_=x64
#$ TOP=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\bin/..
#$ NVVMIR_LIBRARY_DIR=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\bin/../nvvm/libdevice
#$ PATH=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\bin/../nvvm/bin;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\bin;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\bin/../lib;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.21.27702\bin\HostX86\x86;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\VC\VCPackages;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\CommonExtensions\Microsoft\TestWindow;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\bin\Roslyn;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Team Tools\Performance Tools;C:\Program Files (x86)\Microsoft Visual Studio\Shared\Common\VSPerfCollectionTools\vs2019\;C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\CommonExtensions\Microsoft\FSharp\;C:\Program Files (x86)\Windows Kits\10\bin\10.0.17763.0\x86;C:\Program Files (x86)\Windows Kits\10\bin\x86;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\\MSBuild\Current\Bin;C:\Windows\Microsoft.NET\Framework\v4.0.30319;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Tools\;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\bin;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\libnvvp;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\Microsoft VS Code\bin;C:\Program Files\NVIDIA Corporation\NVIDIA NvDLISR;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Program Files\dotnet\;C:\Program Files\Microsoft SQL Server\130\Tools\Binn\;C:\Program Files\Git\cmd;C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\170\Tools\Binn\;C:\Program Files\NVIDIA Corporation\Nsight Compute 2019.3.0\;C:\Program Files\LLVM\bin;;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\;%SYSTEMROOT%\System32\OpenSSH\;C:\Users\lzy\Documents\Source\xmake-io\xmake\xmake;C:\Users\lzy\Documents\Source\xmake io\xmake\xmake;C:\Users\lzy\xmake;C:\Android;C:\Users\lzy\Documents\Source\xmake-io\xmake\xmake;C:\Users\lzy\AppData\Local\Microsoft\WindowsApps;C:\Program Files\Fiddler;C:\Users\lzy\AppData\Local\nvs\default;C:\Users\lzy\AppData\Local\nvs\;C:\Users\lzy\AppData\Local\Microsoft\WindowsApps;;C:\Users\lzy\xmake;C:\Users\lzy\xmake;C:\Users\lzy\xmake;C:\Users\lzy\xmake;C:\Users\lzy\xmake;C:\Users\lzy\xmake;C:\Users\lzy\xmake;C:\Users\lzy\xmake
#$ INCLUDES="-IC:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\bin/../include"
#$ LIBRARIES=  "/LIBPATH:C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\bin/../lib/x64"
#$ CUDAFE_FLAGS=
#$ PTXAS_FLAGS=
nr_common_cood.cu.obj
nr_common.cu.obj
fdpf.cu.obj
nr.cu.obj
dev_solver.cu.obj
#$ erase build//.objs//Test//windows//x64//release//.cuda//devlink//Test_gpucode.cu.obj
#$ lib /nologo  /out:"build//.objs//Test//windows//x64//release//.cuda//devlink//Test_gpucode.cu.obj" "build//.objs//Test//windows//x64//release//src//pf//nr_common_cood.cu.obj" "build//.objs//Test//windows//x64//release//src//pf//nr_common.cu.obj" "build//.objs//Test//windows//x64//release//src//pf//device//fdpf.cu.obj" "build//.objs//Test//windows//x64//release//src//pf//device//nr.cu.obj" "build//.objs//Test//windows//x64//release//src//math//dev_solver.cu.obj"

@waruqi
Copy link
Member

waruqi commented Jun 10, 2019

图片
然后你这libpath在linux也没搞对啊?难道mac上就一个版本的库?

mac上 可能我默认link到 dylib上去了,所以通过了

@waruqi
Copy link
Member

waruqi commented Jun 10, 2019

感觉x86已经被抛弃很久了。。。

mac下也基本不用管x86,目前看 只有win上 说不定需要处理下。

@waruqi
Copy link
Member

waruqi commented Jun 10, 2019

然后 host link 的时候是不是应该把几个cuda的库加上
Win: cudadevrt.lib
Linux: -lcudadevrt -lrt -lpthread -ldl
要链接devlink生成的.o,这几个应该是必须的

恩,可以把缺的补上

@waruqi
Copy link
Member

waruqi commented Jun 10, 2019

这个是不是改成 -branch master,反正只是用来编译新的xmake,用master版的应该就可以,不然这持续集成全炸

当初拉dev的安装,是因为有时候 dev上新增的一些 api ,我就直接用在了 core/xmake.lua 了,用master编译 就通不过了,所以我才改用 每次都拉取最新的 xmake-dev.exe包来编译

不过改成 master,也ok

@waruqi
Copy link
Member

waruqi commented Jun 10, 2019

另外,生成静态库是不需要device-link的,可以看到,直接调用了lib

ok,这块我看下 做些处理

@waruqi
Copy link
Member

waruqi commented Jun 10, 2019

我刚做了些改进和修复,你看看,生成static library这块,我还得研究下,暂时还没处理。。等回头有时间 我再看看

@waruqi
Copy link
Member

waruqi commented Jun 10, 2019

static下我现在跳过device link了,并且cudart库的设置 用户可以在xmake.lua中自己通过 add_links 或者 add_syslinks设置切换 是否用static

你再试试

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants