DAY91:阅读CUDA Environment Variables

  • 1 replies
  • 1171 views
*

sisiy

  • *****
  • 203
    • 查看个人资料
DAY91:阅读CUDA Environment Variables
« 于: 十月 23, 2018, 01:47:14 pm »
J. CUDA Environment VariablesEnvironment variables related to the Multi-Process Service are documented in the Multi-Process Service section of the GPU Deployment and Management guide.
[td=4,1,561]Table 16. CUDA Environment Variables[/td][/tr]
[tr][td=68]Category[/td][td=198]Variable[/td][td=82]Values[/td][td=212]Description[/td][/tr]
[tr][td=1,3,68]Device Enumeration and Properties[/td][td=198]CUDA_​VISIBLE_​DEVICES[/td][td=82]A comma-separated sequence of GPU identifiers[/td][td=212]GPU identifiers are given as integer indices or as UUID strings. GPU UUID strings should follow the same format as given by nvidia-smi, such as GPU-8932f937-d72c-4106-c12f-20bd9faed9f6. However, for convenience, abbreviated forms are allowed; simply specify enough digits from the beginning of the GPU UUID to uniquely identify that GPU in the target system. For example, CUDA_VISIBLE_DEVICES=GPU-8932f937 may be a valid way to refer to the above GPU UUID, assuming no other GPU in the system shares this prefix.

Only the devices whose index is present in the sequence are visible to CUDA applications and they are enumerated in the order of the sequence. If one of the indices is invalid, only the devices whose index precedes the invalid index are visible to CUDA applications. For example, setting CUDA_VISIBLE_DEVICES to 2,1 causes device 0 to be invisible and device 2 to be enumerated before device 1. Setting CUDA_VISIBLE_DEVICES to 0,2,-1,1 causes devices 0 and 2 to be visible and device 1 to be invisible.[/td][/tr]
[tr][td=198]CUDA_​MANAGED_​FORCE_​DEVICE_​ALLOC[/td][td=82]0 or 1 (default is 0)[/td][td=212]Forces the driver to place all managed allocations in device memory.[/td][/tr]
[tr][td=198]CUDA_​DEVICE_​ORDER[/td][td=82]FASTEST_FIRST, PCI_BUS_ID, (default is FASTEST_FIRST)[/td][td=212]FASTEST_FIRST causes CUDA to guess which device is fastest using a simple heuristic, and make that device 0, leaving the order of the rest of the devices unspecified. PCI_BUS_ID orders devices by PCI bus ID in ascending order.[/td][/tr]
[tr][td=1,4,68]Compilation[/td][td=198]CUDA_​CACHE_​DISABLE[/td][td=82]0 or 1 (default is 0)[/td][td=212]Disables caching (when set to 1) or enables caching (when set to 0) for just-in-time-compilation. When disabled, no binary code is added to or retrieved from the cache.[/td][/tr]
[tr][td=198]CUDA_​CACHE_​PATH[/td][td=82]filepath[/td][td=212]Specifies the folder where the just-in-time compiler caches binary codes; the default values are:· on Windows, %APPDATA%\NVIDIA\ComputeCache,· on MacOS, $HOME/Library/Application\ Support/NVIDIA/ComputeCache,· on Linux, ~/.nv/ComputeCache[/td][/tr]
[tr][td=198]CUDA_​CACHE_​MAXSIZE[/td][td=82]integer (default is 33554432 (32 MB) and maximum is 4294967296 (4 GB))[/td][td=212]Specifies the size in bytes of the cache used by the just-in-time compiler. Binary codes whose size exceeds the cache size are not cached. Older binary codes are evicted from the cache to make room for newer binary codes if needed.[/td][/tr]
[tr][td=198]CUDA_​FORCE_​PTX_​JIT[/td][td=82]0 or 1 (default is 0)[/td][td=212]When set to 1, forces the device driver to ignore any binary code embedded in an application (see Application Compatibility) and to just-in-time compile embedded PTX code instead. If a kernel does not have embedded PTX code, it will fail to load. This environment variable can be used to validate that PTX code is embedded in an application and that its just-in-time compilation works as expected to guarantee application forward compatibility with future architectures (see Just-in-Time Compilation).[/td][/tr]
[tr][td=1,4,68]Execution[/td][td=198]CUDA_​LAUNCH_​BLOCKING[/td][td=82]0 or 1 (default is 0)[/td][td=212]Disables (when set to 1) or enables (when set to 0) asynchronous kernel launches.[/td][/tr]
[tr][td=198]CUDA_​DEVICE_​MAX_​CONNECTIONS[/td][td=82]1 to 32 (default is 8)[/td][td=212]Sets the number of compute and copy engine concurrent connections (work queues) from the host to each device of compute capability 3.5 and above.[/td][/tr]
[tr][td=198]CUDA_​AUTO_​BOOST[/td][td=82]0 or 1[/td][td=212]Overrides the autoboost behavior set by the --auto-boost-default option of nvidia-smi. If an application requests via this environment variable a behavior that is different from nvidia-smi's, its request is honored if there is no other application currently running on the same GPU that successfully requested a different behavior, otherwise it is ignored.[/td][/tr]
[tr][td=198]CUDA_​ENABLE_​CRC_​CHECK[/td][td=82]0 or 1 (default is 0)[/td][td=212]When set to 1, commands and data sent to the GPU are error-checked to ensure they are not corrupted.[/td][/tr]
[tr][td=68]cuda-gdb (on Mac and Linux platforms)[/td][td=198]CUDA_​DEVICE_​WAITS_​ON_​EXCEPTION[/td][td=82]0 or 1 (default is 0)[/td][td=212]When set to 1, a CUDA application will halt when a device exception occurs, allowing a debugger to be attached for further debugging.[/td][/tr]
[tr][td=1,5,68]Driver-Based Profiler (these variables have no impact on the Visual Profiler or the command line profiler nvprof)[/td][td=198]CUDA_​DEVICE[/td][td=82]Integer (default is 0)[/td][td=212]Specifies the index of the device to profile.[/td][/tr]
[tr][td=198]COMPUTE_​PROFILE[/td][td=82]0 or 1 (default is 0)[/td][td=212]Disables profiling (when set to 0) or enables profiling (when set to 1).[/td][/tr]
[tr][td=198]COMPUTE_​PROFILE_​CONFIG[/td][td=82]Path[/td][td=212]Specifies the configuration file to set profiling options and select performance counters.[/td][/tr]
[tr][td=198]COMPUTE_​PROFILE_​LOG[/td][td=82]Path[/td][td=212]Specifies the file used to save the profiling output. In case of multiple contexts, use '%d' in the COMPUTE_PROFILE_LOG to generate separate output files for each context - with '%d' substituted by the context number.[/td][/tr]
[tr][td=198]COMPUTE_​PROFILE_​CSV[/td][td=82]0 or 1 (default is 0)[/td][td=212]When set to 1, the output will be in comma-separated format.[/td][/tr]
[/table]

*

sisiy

  • *****
  • 203
    • 查看个人资料
(无标题)
« 回复 #1 于: 十月 23, 2018, 03:32:27 pm »
今天章节的主要内容是,一个CUDA应用在执行前,用户可以设定的和CUDA相关的环境变量,从而能在不改动代码的情况下,影响该CUDA应用执行的方方面面。注意本表格有些内容已经在当前的CUDA版本和驱动版本中,不再正确(有很多历史遗留)。
先说一下几个重要的环境变量。

其中第一个就是CUDA_VISIBLE_DEVICES, 这个环境变量很有用。主要作用有两点:
(1)是可以控制设定该环境变量后,后续的CUDA应用能使用,当前多卡系统上的哪些卡。
(2)则是可以用该环境变量,调整后续启动的CUDA应用,所看到的多卡系统上的,卡的顺序.

这两点应用看起来简单,但用好了有很多很方便的地方,例如看我们论坛上的案例:http://bbs.gpuworld.cn/thread-58820-1-1.html

例如这个帖子。用户试图快速测试双卡能否将一个任务加快两倍。那么对他来说,在不改动代码的情况下(例如需要2个Host线程,每个线程针对一张卡,然后处理),直接通过设定CUDA_VISIBLE_DEVICES变量,分别让它等于0和1,然后直接继续启动没有修改过的程序,即可直接将程序分布在2个卡上运行。

这种方式作为测试,非常方便。

此外,如果一个测试开发平台,例如具有两张卡,分别是0号卡GTX1050,和1号卡2080,那么用户可以快速的通过设定该变量,可以快速的设定值为"1,0"即可快速的将这两张卡的顺序颠倒过来,方便测试。

需要注意的是,当用户选择不同的shell的时候,bash可以通过export CUDA_VISIBLE_DEVICES=1,0来设定。

而CSH家族的shell, 则需要使用setenv CUDA_VISIBLE_DEVICE "1,0",注意这里的等号和空格的变化,以及,引号有无的变化。至于如果想通过GPU的UUID编号,而不是0,1,2,3这样的顺序号来指定卡,可以直接先通过nvidia-smi -a来查询到这些卡的UUID编号(一个很长的字符串来标识每张卡)。


此外,关于第二栏的PTX到CUBIN的JIT的cache文件的问题,如果你还记得之前我们的文章,一个编译好的CUDA应用中(Runtime API应用),里面会被嵌入GPU代码,这些GPU代码往往是你的kernel,最终要在你的卡上运行。这种嵌入在你的可执行文件中的代码,可以分成两种类别,一种是文本格式的PTX代码,这种PTX代码是一种通用的GPU虚拟机格式,可以跨很多代卡(例如从Kepler到Turing)都能运行。而另外一种代码则是针对具体架构的(例如计算能力6.1)特定的CUBIN(SASS)代码,这种代码只能在特定的架构上运行。后者实际上是你的具体的某个GPU所能执行的唯一的代码。

为了能让前者(PTX)在很多不同的GPU架构上执行(例如你开发在Kepler上,用户运行在Pascal上),实际上需要进行一种转换,转换成后者,才能真正执行,这个过程叫JIT(即时编译,细节看我们之前的章节)。而这里的有一些相关变量可以控制这个JIT过程。

大家可以直接阅读一下这里的几个变量。

需要说明的是:目前已知深度学习部分框架经常会崩掉,需要用户手工经常来清理掉这个JIT结果缓存,否则在重装系统前,(其实是重装驱动即可),

这个崩溃会反复出现。例如某些框架需要发生特定的意外情况后,需要你手工:
rm -rf ~/.nv回车

来清理掉Linux上的对应的JIT结果缓存文件(具体路径受本章节的CUDA_CACHE_PATH环境变量控制,你如果没改就是上面这个,详情见本章节说明),否则你很难找到问题。这是一点。

你也可以考虑设定CUDA_CACHE_DISABLE为1后(利用刚才说的export或者setenv),再运行你的深度学习框架或者应用,这样可能一定程度的增加初始化的启动延迟,但可以一定程度的规避你需要手工清理缓存的问题。这是一点。


其次,实际上在你每次更新驱动的时候,该缓存总是会被自动清除的,所以有时候升级一下驱动,问题消失,也是一种办法。

另外一个的重要环境变量是CUDA_LAUNCH_BLOCKING, 这个可以辅助调试,所有的kernel启动(例如你的一次<<<>>>()语法启动的GPU Kernel),会变成同步的,而不是默认的GPU kernel是异步执行的。

默认情况是GPU kernel启动后,例如需要执行个500ms,期间CPU可以继续往下执行自己的CPU代码,设定该环境变量后,kernel完成前或者挂掉前,CPU代码不会继续执行。这样对于正常的生产运行,会一定程度的影响CUDA应用的执行效率。但对于辅助调试来说,它可以快速的暴露你的kernel中存在的问题,避免出现kernel的确挂了,但是你的CPU代码已经往下执行了很久很久了,在很久的某处,通过后续的某个同步调用,返回了很久很久之前的某个kernel的异步错误,让人摸不到头脑的情况。这个环境变量设定后,可以方便的阻止这种情况的发生,让你能够挂在出错位置的附近,有利于调试。



 http://bbs.gpuworld.cn/thread-58848-1-1.html  引用了我们自己的之前的章节。引用:“例如kernel中途访存挂了,这个时候因为时机已经错过去了,那么只能由后续的其他无关调用(例如你分配一段显存)来报告。所以用户会看到一个奇特的现象:后面无论调用什么都是错的,哪怕检查了代码,后面的行写的看上去都没有问题。用户就会困惑..."

和引用:
“这就是异步错误。很多新人都不知道这点,导致无法定位错误位置(他们会定位到其他不相关的后续位置,例如这个楼主)...."

而通过使用该环境变量,可以一定程度的减少这种情况的发生。因为设定了该环境变量后,异步错误会变成同步错误,虽然会影响性能(你反正在调试,都算错了还管性能?),但是的确方便了很多。




关于CUDA_DEVICE_MAX_CONNECTIONS这个环境变量,该环境变量在当前Hyper-Q引入的时候,流行一时。计算能力3.5+的卡,具有多个硬件的命令队列,而这些硬件的命令队列,会映射到你的CUDA代码中的创建的流上(streams)。你可以继续无限制多的创建很多流,例如200个流,但是实际上硬件的实际存在的队列数量是有限的,例如32个。这200个流会映射到这32个实际的队列上,例如说,一种映射方式可能是:100号流,和132号流实际上对应的是同一个硬件队列。类似这种的。
从计算能力3.5起,引入了Hyper-Q,将原本的只有1个命令队列,扩展到了32个队列,从而有效的提升了多流的命令间的实际并行能力(前提是这些命令,例如kernel启动,并无逻辑依赖关系)。

而本环境变量,则可以控制每个CUDA应用的进程,实际能使用的硬件队列的数量。
例如这里提示的8个。
需要注意的两点:
(1)当年Hyper-Q推出的时候,用这个更好的控制用MPI进行任务并行的多个CUDA进程之间的硬件队列使用。

(2)从Hyper-Q推出(3.5)以后,更新的卡(5.0+,Maxwell+),NV并未更新或者提供新的卡上的Hyper-Q能力的信息,也不知道这些卡上的现在的硬件任务队列个数是多少。

用户需要自行进行这些卡上的时间。

实际上我们的论坛的用户们反馈,较新的卡上,设定该环境变量并无太大作用。这个请各个用户自行尝试。
然后是一个CUDA_DEVICE_WAITS_ON_EXCEPTION

本章节的描述是,设定他后可以让挂掉kernel的CUDA应用进程暂停,然后附加上调试器用来验尸(post-mortem debugging), 但是实际上在Linux下并无效果,设定后,会提示“进程XXX发生了设备上的错误,已经被暂停,请附加调试器到YYYY的PID(进程编号)上来调试”。但是实际上并没有停住。


用户应当考虑自行实验这点。

或者一般的,应当直接在调试器下启动CUDA应用,例如在cuda-gdb下启动你的cuda进程。这样总是可以的。

最后关于Driver-Based Profiler,这个长期以来,是存在的CUDA里面的秘密和几乎没有人提到的另外一个profiler,并非我们现在使用的nvprof(命令行)或者它的nvvp外壳(图形界面)。该driver-based profiler以前也叫command line profiler, 通过本章节最后说的这些环境变量进行控制。*这也是以前,NV唯一提供的,能对它自家的平台上的OpenCL代码,进行profiling的唯一方式,只是NV没有宣传,这种方式的确可以进行OCL的应用的性能剖析  ,NV能找到的文档中,宣传的这个是另外一种CUDA代码的分析方式,但实际上是CUDA和OpenCL都可以的。但是很遗憾,很久很久之前,该功能就被拿掉了,大约在CUDA 8之前的年代吧。

也就是说,现在你看到的今天的阅读,本章节最后部分是错误的,已经没用了。

同时,这也很遗憾的告诉我们,N家平台上,至此完全取消了OpenCL的分析功能(你用nvprof分析一个OCL的kernel,会直接提示,该进程并未启动任何Kernel的)。

因此本章节的最后部分,如果用户还需要,可以降级到7.5或者更早版本的CUDA Toolkit和配套驱动使用。

现在已经不能用了。但需要提示的是,在N家平台上试图使用OpenCL,本身可能就是一个错误。(还有众多其他方面的问题)。