
{"id":1342,"date":"2025-09-25T13:44:04","date_gmt":"2025-09-25T10:44:04","guid":{"rendered":"https:\/\/paragroup.cse.uoi.gr\/wpsite\/?page_id=1342"},"modified":"2025-12-15T16:21:48","modified_gmt":"2025-12-15T14:21:48","slug":"ompi-offloading-to-cuda-gpus","status":"publish","type":"page","link":"https:\/\/paragroup.cse.uoi.gr\/wpsite\/software\/ompi\/documentation\/ompi-offloading-to-cuda-gpus\/","title":{"rendered":"OMPi: Offloading to CUDA GPUs"},"content":{"rendered":"<h2>Introduction<\/h2>\n<p>OMPi supports offloading to CUDA GPUs through the dedicated <code>cuda<\/code> module. Initially, the compiler generates CUDA kernel source files\u00a0for each OpenMP <code>target<\/code> directive appearing in the user application. The cuda module is responsible for:<\/p>\n<ol>\n<li>Compiling the CUDA kernels to CUDA executables,<\/li>\n<li>Initializing\/finalizing a CUDA device,<\/li>\n<li>Transferring data between the CPU and a CUDA device,<\/li>\n<li>Offloading the CUDA executables to the requested CUDA device.<\/li>\n<\/ol>\n<h2>Requirements<\/h2>\n<p>The current requirements of the <code>cuda<\/code> module are the following:<\/p>\n<ul>\n<li>CUDA Toolkit version 9.0 or greater, with working CUDA\u00a0drivers<\/li>\n<li>CUDA architecture version 3.5 or greater (for each GPU)<\/li>\n<\/ul>\n<p>Before proceeding with the installation, please make sure that:<\/p>\n<ul>\n<li><code>&lt;cuda-install-dir&gt;\/bin<\/code> is in your <code>PATH<\/code> environment variable<\/li>\n<li><code>&lt;cuda-install-dir&gt;\/lib64<\/code> is\u00a0in your <code>LD_LIBRARY_PATH<\/code> environment variable<\/li>\n<\/ul>\n<p>where <code>&lt;cuda-install-dir&gt;<\/code> is the installation directory of the CUDA toolkit.<\/p>\n<h2>Installing OMPi<\/h2>\n<p>The first step is to\u00a0deploy OMPi on your system. Initially, you need to set up OMPi as follows:<\/p>\n<pre>meson setup build --prefix=&lt;install-dir&gt;<\/pre>\n<div class=\"su-spoiler su-spoiler-style-default su-spoiler-icon-plus su-spoiler-closed\" data-anchor=\"jit-conf\" data-scroll-offset=\"0\" data-anchor-in-url=\"no\"><div class=\"su-spoiler-title\" tabindex=\"0\" role=\"button\"><span class=\"su-spoiler-icon\"><\/span>Advanced configuration: Just-in-time kernel compilation<\/div><div class=\"su-spoiler-content su-u-clearfix su-u-trim\">\n<p>The <code>cuda<\/code> module operates either in PTX-JIT or in CUBIN mode. These modes affect the output kernel executable format, as well as the actions taking place in the compiler and runtime parts of OMPi.\u00a0<\/p>\n<p>Both modes have their positive and negative aspects. CUBIN mode removes many runtime overheads but adds a notable delay during kernel compilation. On the other hand, PTX-JIT mode leads to smaller compilation times as PTX file production is much lighter than binary production, however it causes extra overheads during runtime. These overheads are related to the compilation and linking of the PTX file with the appropriate device libraries; they can be, however, minimized by utilizing CUDA JIT cache, a global disk cache for loaded PTX files.\u00a0<\/p>\n<p>To make sure the cache is enabled,\u00a0set the corresponding environment variable:<\/p>\n<pre>export CUDA_CACHE_DISABLE=0<\/pre>\n<p>OMPi by default produces PTX files. To disable the PTX-JIT mode and have OMPi produce executable CUBIN files, set up OMPi with the\u00a0<code>-Dcuda-jit<\/code>\u00a0flag:<\/p>\n<pre>meson setup build --prefix=\u2039install-dir\u203a <strong>-Dcuda-jit=false<\/strong><\/pre>\n<\/div><\/div>\n<p>Then OMPi can be compiled and installed as usual:<\/p>\n<pre>cd build\/\r\nmeson compile\r\nmeson install<\/pre>\n<p>During the installation process, if your system satisfies the minimum requirements and has at least one CUDA GPUs installed, OMPi will automatically build the <code>cuda<\/code> module.\u00a0The correct installation of the module can be verified by running:<\/p>\n<pre>ompiconf --devvinfo<\/pre>\n<p>which lists all the identified modules\/devices, along with their <em>numeric device IDs<\/em>. If the above command fails to show a CUDA GPU, please revisit the minimum requirements and ensure you have installed OMPi correctly.<\/p>\n<div class=\"su-spoiler su-spoiler-style-default su-spoiler-icon-plus su-spoiler-closed\" data-anchor=\"devinfo-example\" data-scroll-offset=\"0\" data-anchor-in-url=\"no\"><div class=\"su-spoiler-title\" tabindex=\"0\" role=\"button\"><span class=\"su-spoiler-icon\"><\/span>Sample output of devvinfo<\/div><div class=\"su-spoiler-content su-u-clearfix su-u-trim\">\n<p>The <code>ompiconf --devvinfo<\/code> command should give an output similar to the following (here a Tesla P40 GPU was identified by OMPi):<\/p>\n<pre>MODULE [cuda]:\r\n------\r\nOMPi CUDA device module.\r\nAvailable devices : 1\r\n\r\ndevice id &lt; 0 &gt; { \r\n GPU device name : Tesla P40\r\n Compute capability : 6.1\r\n CUDA toolkit version : 12.4\r\n NVIDIA driver version : 550.90.07\r\n Num of multiprocessors : 30\r\n Cores per multiprocessor : 128\r\n Total num of cores : 3840\r\n Maximum thread block size : 1024\r\n Global memory : 22.4 GBytes\r\n Shared memory per block : 48 KBytes\r\n}\r\n------<\/pre>\n<\/div><\/div>\n<h2>Quick start<\/h2>\n<p>Compiling your OpenMP application with CUDA GPU offloading requires a simple <code>--devs=cuda<\/code> <strong>OR <\/strong>the generic<strong>\u00a0<\/strong><code>--devs=all<\/code>\u00a0argument:<\/p>\n<pre>ompicc --devs=cuda app.c<\/pre>\n<p>The compiler will produce the main application executable (<code>a.out<\/code>) and several CUDA kernel executables, one for each OpenMP <code>target<\/code> construct in the\u00a0application.<\/p>\n<div class=\"su-spoiler su-spoiler-style-default su-spoiler-icon-plus su-spoiler-closed\" data-anchor=\"sample-app\" data-scroll-offset=\"0\" data-anchor-in-url=\"no\"><div class=\"su-spoiler-title\" tabindex=\"0\" role=\"button\"><span class=\"su-spoiler-icon\"><\/span>Sample OpenMP application utilizing the GPU<\/div><div class=\"su-spoiler-content su-u-clearfix su-u-trim\">\n<p>Here is a sample application that can be used to verify the\u00a0successful deployment of the <code>cuda<\/code> module:<\/p>\n<pre><strong>#include<\/strong> &lt;stdio.h&gt;\r\n<strong>#include<\/strong> &lt;omp.h&gt;\r\n\r\n<strong>int<\/strong> main(<strong>void<\/strong>)\r\n{\r\n    \/* \r\n     * Expected result (assuming that the GPU device ID is 0):\r\n     * Running on CUDA device \r\n     *\/\r\n<strong><span class=\"cp\">    #pragma omp target device(0)<\/span><\/strong>\r\n    <span class=\"p\">{<\/span>\r\n        <strong><span class=\"k\">if<\/span> <\/strong><span class=\"p\">(<\/span><span class=\"n\">omp_is_initial_device<\/span><span class=\"p\">())<\/span> \r\n            <span class=\"n\">printf<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Running on host<\/span><span class=\"se\">\\n<\/span><span class=\"s\">\"<\/span><span class=\"p\">);<\/span>    \r\n<strong><span class=\"k\">        else<\/span> <\/strong>\r\n            <span class=\"n\">printf<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Running on CUDA device\\n\"); <\/span>\r\n    <span class=\"p\">}\r\n    <strong>return<\/strong> 0;\r\n}\r\n<\/span><\/pre>\n<\/div><\/div>\n<div class=\"su-spoiler su-spoiler-style-default su-spoiler-icon-plus su-spoiler-closed\" data-anchor=\"multiple-jobs\" data-scroll-offset=\"0\" data-anchor-in-url=\"no\"><div class=\"su-spoiler-title\" tabindex=\"0\" role=\"button\"><span class=\"su-spoiler-icon\"><\/span>Advanced usage: Multiple compilation jobs<\/div><div class=\"su-spoiler-content su-u-clearfix su-u-trim\">\n<p>When an\u00a0application contains several <code>target<\/code> regions, compilation times may become substantial. One can generate multiple compilation jobs that handle the compilation of different kernels in parallel, by using the\u00a0<code>-j&lt;number&gt;<\/code> device option. For example to have 4 parallel kernel compilation jobs, use <code>ompicc<\/code> as follows:<\/p>\n<pre>ompicc --devs=cuda <strong>--devopt -j4<\/strong> app.c<\/pre>\n<\/div><\/div>\n<h2>Notes<\/h2>\n<p>The OMPi cuda module has been tested with the following CUDA GPUs:<\/p>\n<ul>\n<li>Ampere A2<\/li>\n<li>Tesla P40<\/li>\n<li>Tegra X1 (Jetson Nano)<\/li>\n<li>GTX 1050 Ti<\/li>\n<li>GTX 970<\/li>\n<li>GT 1030<\/li>\n<li>GT 730<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Introduction OMPi supports offloading to CUDA GPUs through the dedicated cuda module. Initially, the compiler generates CUDA kernel source files\u00a0for each OpenMP target directive appearing in the user application. The cuda module is responsible for: Compiling the CUDA kernels to CUDA executables, Initializing\/finalizing a CUDA device, Transferring data between the CPU and a CUDA device, [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":0,"parent":120,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-1342","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/paragroup.cse.uoi.gr\/wpsite\/wp-json\/wp\/v2\/pages\/1342","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/paragroup.cse.uoi.gr\/wpsite\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/paragroup.cse.uoi.gr\/wpsite\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/paragroup.cse.uoi.gr\/wpsite\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/paragroup.cse.uoi.gr\/wpsite\/wp-json\/wp\/v2\/comments?post=1342"}],"version-history":[{"count":12,"href":"https:\/\/paragroup.cse.uoi.gr\/wpsite\/wp-json\/wp\/v2\/pages\/1342\/revisions"}],"predecessor-version":[{"id":1434,"href":"https:\/\/paragroup.cse.uoi.gr\/wpsite\/wp-json\/wp\/v2\/pages\/1342\/revisions\/1434"}],"up":[{"embeddable":true,"href":"https:\/\/paragroup.cse.uoi.gr\/wpsite\/wp-json\/wp\/v2\/pages\/120"}],"wp:attachment":[{"href":"https:\/\/paragroup.cse.uoi.gr\/wpsite\/wp-json\/wp\/v2\/media?parent=1342"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}