Developer Guide and Reference

  • 2021.4
  • 09/27/2021
  • Public Content

Frequently Asked Questions

This page contains the most frequently asked questions about the Intel® DPC++ Compatibility Tool.

General Information

How do I migrate source files that are using C++11 or newer C++ standard features on Linux* and Windows*?
On Linux, the default C++ standard for the Intel® DPC++ Compatibility Tool’s parser is C++98, with some C++11 features accepted. If you want to enable other C++11 or newer standard features in the Intel® DPC++ Compatibility Tool, you need to add the
--extra-arg="-std=<value>"
option to the command line. The supported values are:
  • c++11
  • c++14
  • c++17
On Windows, the default C++ standard for the Intel® DPC++ Compatibility Tool’s parser is C++14. If you want to enable C++17 features in the Intel® DPC++ Compatibility Tool, you need to add the option
--extra-arg="-std=c++17"
to the command line.
How do I migrate files on Windows when using a CMake project?
For a CMake project on a Windows OS, you can use CMake to generate Microsoft Visual Studio* project files (
vcxproj
files). Then choose one of the following options:
  • Migrate the source files on the command line by using the
    --vcxprojfile
    option of the Intel® DPC++ Compatibility Tool.
  • Migrate the entire project in Microsoft Visual Studio with an Intel® DPC++ Compatibility Tool Microsoft Visual Studio plugin.
How is the migrated code formatted?
The Intel® DPC++ Compatibility Tool provides two options to control the format of migrated code:
--format-range
and
--format-style
.
If input source code is well formatted, the Intel® DPC++ Compatibility Tool will use default options settings
--format-range
and
--format-style
to format the resulting code.
If input source code is not well formatted (for example, the tool detects mixed use of tabs and spaces or mixed indents) you can do one of the following:
  • The Intel® DPC++ Compatibility Tool will try to detect the indent size of the original code and apply it to the resulting code. You can guide the tool by setting
    TabWidth
    and
    UseTab
    in the
    .clang-format
    file. Because the input source code is not well formatted, the indents in the resulting code may still be inconsistent.
  • Run the Intel® DPC++ Compatibility Tool with the
    --format-range=all
    option to format the entire resulting file. The change between input source code and resulting source code may be large and make it more difficult to compare the code.
  • Format your input source code, then use the Intel® DPC++ Compatibility Tool with the same
    .clang-format
    file for migration.
Why does the compilation database (compile_commands.json) not contain all source file(s) in the project?
In the project build folder, the command
intercept-build make [target]
is used to generate the compilation database. The content of the compilation database depends on the optional [target] parameter. If you need to get the list of files corresponding to default build target, do not specify the [target] parameter.
How do I use the migrated module file in the new project?
.cu
module files are compiled with the
-ptx
or
-cubin
options in the original project and dynamically loaded into other
*.cu
files with
cuModuleLoad()
or
cuModuleLoadData()
.
The Intel® DPC++ Compatibility Tool migrates module file code in the same way as other
*.cu
files. In addition, it adds a wrapper function for each function in the module file that has the
_global_
attribute.
You can compile the migrated module file into a dynamic library and load the library with a dynamic library API appropriate to your platform. For example:
  • In Linux, load a dynamic library (
    .so
    ) using
    dlopen()
  • In Windows, load a dynamic library (
    .dll
    ) using
    LoadLibraryA()
Is the memory space allocated by sycl::malloc_device, sycl::malloc_host, and dpct::dpct_malloc initialized?
The memory allocated by
sycl::malloc_device
,
sycl::malloc_host
, and
dpct::dpct_malloc
is not initialized. If your program explicitly or implicitly relies on the initial value of newly allocated memory, the program may fail at runtime. Adjust your code to avoid such failures.
For example, the following original code:
// original code int *device_mem = nullptr;device_mem = sycl::malloc_device<int>(size, dpct::get_default_queue()); device_mem[0] += somevalue;
is adjusted to initialize the newly allocated memory to 0 before use:
// fixed DPC++ code int *device_mem = nullptr;device_mem = sycl::malloc_device<int>(size, dpct::get_default_queue()); dpct::get_default_queue().memset(0, size).wait(); device_mem[0] += somevalue;

Troubleshooting

How do I fix an error such as “error: unknown type name” when I migrate files with “dpct –in-root=srcdir –out-root=dstdir *.cu”?
The problem may be caused by files in the
*.cu
list, which can be used as header files (included with an
#include
statement) and are not supposed to be parsed as a standalone file. In this case, the Intel® DPC++ Compatibility Tool reports an error if it cannot parse the file because the file depends on the definitions/declarations in other files. Use one of the methods below to migrate your content:
  • Rely on the Intel® DPC++ Compatibility Tool to decide which files to migrate with:
    compile_commands.json: “dpct -p=compile_commands.json --in-root=srcdir --out-root=dstdir”
  • Manually pass specific files to migrate, but do not pass the files that are included in other files and not supposed to be compiled as a standalone file in the original application. The header files are migrated automatically when they are included by the files provided as the input to the tool and are located within the
    in-root
    folder:
    dpct --in-root= srcdir --out-root=dstdir sample.cu
How do I fix a parsing error such as “no member named ‘max’ in namespace ‘std’” or “no member named ‘min’ in namespace ‘std’” when migrating code on Windows?
Use one of the following methods to resolve the error:
  • Add
    #include <algorithm>
    to the source file before using
    std::min
    and
    std::max
  • Define the NOMINMAX macro by inserting
    #define NOMINMAX
    before including
    WinDef.h
How do I fix a compilation error such as “error: dlopen not declared” when I compile code on a Windows machine, that was originally migrated on Linux?
When the Intel® DPC++ Compatibility Tool generates the source code, it uses dynamic loading APIs specific to the OS on which the Intel® DPC++ Compatibility Tool is running.
For example,
dlopen
,
dlclose
, and
dlsym
are used on Linux and
LoadLibraryA
,
FreeLibrary
, and
GetProcAddress
are used on Windows.
If your code was migrated on a OS that is different from the OS you need to compile the generated code on, migrate the project again with the Intel® DPC++ Compatibility Tool on the target OS or fix the code manually.
Why didn’t the “atomic*” APIs get migrated?
The Intel® DPC++ Compatibility Tool may assume that the “atomic*” APIs are user-defined APIs, in which case they are not migrated.
This can occur in the following scenarios:
  • The CUDA include path is specified by both
    --cuda-include-path
    and
    -I*
    , but the paths are different
  • The CUDA include path is specified by
    -I*
    , but there are other CUDA include files located on the default CUDA install path
To make sure “atomic*” APIs are migrated, don’t use
-I*
to specify the CUDA include path with the
dpct
migration command. Instead, use only
--cuda-include-path
to specify the CUDA include path.
Why did my migration fail with “error: restrict requires a pointer or reference”?
The C++ standard does not support the restrict qualifier and the C standard supports the restrict qualifier only on pointers to an object type.
Based on these language standards the Intel® DPC++ Compatibility Tool emits the parsing error.
You may need to adjust the source code.
How do I resolve incorrect runtime behavior for dpct::dev_mgr and dpct:mem_mgr in a library project that is loaded more than once in another application?
dpct::dev_mgr
and
dpct::mem_mgr
are singleton classes in the Intel® DPC++ Compatibility Tool helper functions. When the helper function headers are used to build an executable project, both
dpct::dev_mgr
and
dpct::mem_mgr
will have only one instance in the executable. However, when the helper function headers are used to build a library project and the library project is loaded more than once with
dlopen()
(or
LoadLibraryA()
for Windows) in an application, more than two instances of
dpct::dev_mgr
and
dpct::mem_mgr
will be created and result in incorrect runtime behavior.
For example, both files
libA.cpp
and
libB.cpp
include the Intel® DPC++ Compatibility Tool helper function header
dpct.hpp
, and they are built into dynamic libraries
libA.so
and
libB.so
respectively. If an application
main.cpp
imports the libraries with
dlopen()
, there will be two instances of
dpct::dev_mgr
and
dpct::mem_mgr
in the runtime of the application.
To resolve this issue, separate the implementation and the declaration of
dpct::dev_mgr
and
dpct::mem_mgr
in the Intel® DPC++ Compatibility Tool helper function:
  1. Create a new C++ file
    dpct_helper.cpp
    .
  2. Move the implementation of
    instance()
    in
    class dev_mgr
    from
    dpct/device.hpp
    to
    dpct_helper.cpp
    .
    For example, the original
    dpct/device.hpp
    :
    class dev_mgr { public: static dev_mgr &instance() { // the implementation and the declaration of dev_mgr::instance static dev_mgr d_m; return d_m; } ... }
    is updated to:
    class dev_mgr { public: static dev_mgr &instance();//the declaration of dev_mgr::instance ... }
    and the new
    dpct_helper.cpp
    now contains the implementation of
    dev_mgr::instance()
    :
    #include <dpct/device.hpp> dpct::dev_mgr &dev_mgr::instance(){ // the implementation of dev_mgr::instance static dev_mgr d_m; return d_m; }
  3. Similar to step two, move the implementation of
    instance()
    in the
    class mem_mgr
    from
    dpct/memory.hpp
    to
    dpct_helper.cpp
    .
  4. Build
    dpct_helper.cpp
    into a dynamic library
    libdpct_helper
    .
    • In Linux:
      dpcpp -g -shared -o libdpct_helper.so -fPIC ./dpct_helper.cpp
    • In Windows:
      cl.exe /LD dpct_helper.cpp
  5. Add library
    libdpct_helper
    to the environment variables.
    • In Linux: Add the location of
      libdpct_helper.so
      into
      LD_LIBRARY_PATH
      .
    • In Windows: Add the location of
      libdpct_helper.dll
      into
      PATH
      .
  6. Dynamically link
    libdpct_helper
    when building libraries and applications.
After performing the update steps, all the libraries and applications will share the same instance of the device manager
dpct::dev_mgr
and the memory manager
dpct::mem_mgr
in Intel® DPC++ Compatibility Tool helper functions.
Why do I get “warning: shift count >= width of type” when I compile migrated code with the Intel® oneAPI DPC++/C++ Compiler?
Shifting bits where the shift is greater than the type length is undefined behavior for the Intel® oneAPI DPC++/C++ Compiler and may result in different behavior on different devices. Adjust your code to avoid this type of shift.
For example, the migrated DPC++ code:
// migrated DPC++ code void foo() { ... unsigned int bit = index[tid] % 32; unsigned int val = in[tid] << 32 - bit; ... }
is adjusted to avoid a bit shift that is greater than the type length:
// fixed DPC++ code void foo() { ... unsigned int bit = index[tid] % 32; unsigned int val; if(32 - bit == 32) val = 0; else val = in[tid] << 32 - bit; ... }

Product and Performance Information

1

Performance varies by use, configuration and other factors. Learn more at www.Intel.com/PerformanceIndex.