HIP: Heterogenous-computing Interface for Portability
HIP Debugging

There are some techniques provided in HIP for developers to trace and debug codes during execution, this section describes some details and practical suggestions on debugging.

Table of Contents

Debugging tools

Using ltrace

ltrace is a standard linux tool which provides a message to stderr on every dynamic library call. Since ROCr and the ROCt (the ROC thunk, which is the thin user-space interface to the ROC kernel driver) are both dynamic libraries, this provides an easy way to trace the activity in these libraries. Tracing can be a powerful way to quickly observe the flow of the application before diving into the details with a command-line debugger. ltrace is a helpful tool to visualize the runtime behavior of the entire ROCm software stack. The trace can also show performance issues related to accidental calls to expensive API calls on the critical path.

Here's a simple sample with command-line to trace hip APIs and output:

1 $ ltrace -C -e "hip*" ./hipGetChanDesc
2 hipGetChanDesc->hipCreateChannelDesc(0x7ffdc4b66860, 32, 0, 0) = 0x7ffdc4b66860
3 hipGetChanDesc->hipMallocArray(0x7ffdc4b66840, 0x7ffdc4b66860, 8, 8) = 0
4 hipGetChanDesc->hipGetChannelDesc(0x7ffdc4b66848, 0xa63990, 5, 1) = 0
5 hipGetChanDesc->hipFreeArray(0xa63990, 0, 0x7f8c7fe13778, 0x7ffdc4b66848) = 0
6 PASSED!
7 +++ exited (status 0) +++

Another sample below with command-line only trace hsa APIs and output:

1 $ ltrace -C -e "hsa*" ./hipGetChanDesc
2 libamdhip64.so.4->hsa_init(0, 0x7fff325a69d0, 0x9c80e0, 0 <unfinished ...>
3 libhsa-runtime64.so.1->hsaKmtOpenKFD(0x7fff325a6590, 0x9c38c0, 0, 1) = 0
4 libhsa-runtime64.so.1->hsaKmtGetVersion(0x7fff325a6608, 0, 0, 0) = 0
5 libhsa-runtime64.so.1->hsaKmtReleaseSystemProperties(3, 0x80084b01, 0, 0) = 0
6 libhsa-runtime64.so.1->hsaKmtAcquireSystemProperties(0x7fff325a6610, 0, 0, 1) = 0
7 libhsa-runtime64.so.1->hsaKmtGetNodeProperties(0, 0x7fff325a66a0, 0, 0) = 0
8 libhsa-runtime64.so.1->hsaKmtGetNodeMemoryProperties(0, 1, 0x9c42b0, 0x936012) = 0
9 ...
10 <... hsaKmtCreateEvent resumed> ) = 0
11 libhsa-runtime64.so.1->hsaKmtAllocMemory(0, 4096, 64, 0x7fff325a6690) = 0
12 libhsa-runtime64.so.1->hsaKmtMapMemoryToGPUNodes(0x7f1202749000, 4096, 0x7fff325a6690, 0) = 0
13 libhsa-runtime64.so.1->hsaKmtCreateEvent(0x7fff325a6700, 0, 0, 0x7fff325a66f0) = 0
14 libhsa-runtime64.so.1->hsaKmtAllocMemory(1, 0x100000000, 576, 0x7fff325a67d8) = 0
15 libhsa-runtime64.so.1->hsaKmtAllocMemory(0, 8192, 64, 0x7fff325a6790) = 0
16 libhsa-runtime64.so.1->hsaKmtMapMemoryToGPUNodes(0x7f120273c000, 8192, 0x7fff325a6790, 0) = 0
17 libhsa-runtime64.so.1->hsaKmtAllocMemory(0, 4096, 4160, 0x7fff325a6450) = 0
18 libhsa-runtime64.so.1->hsaKmtMapMemoryToGPUNodes(0x7f120273a000, 4096, 0x7fff325a6450, 0) = 0
19 libhsa-runtime64.so.1->hsaKmtSetTrapHandler(1, 0x7f120273a000, 4096, 0x7f120273c000) = 0
20 <... hsa_init resumed> ) = 0
21 libamdhip64.so.4->hsa_system_get_major_extension_table(513, 1, 24, 0x7f1202597930) = 0
22 libamdhip64.so.4->hsa_iterate_agents(0x7f120171f050, 0, 0x7fff325a67f8, 0 <unfinished ...>
23 libamdhip64.so.4->hsa_agent_get_info(0x94f110, 17, 0x7fff325a67e8, 0) = 0
24 libamdhip64.so.4->hsa_amd_agent_iterate_memory_pools(0x94f110, 0x7f1201722816, 0x7fff325a67f0, 0x7f1201722816 <unfinished ...>
25 libamdhip64.so.4->hsa_amd_memory_pool_get_info(0x9c7fb0, 0, 0x7fff325a6744, 0x7fff325a67f0) = 0
26 libamdhip64.so.4->hsa_amd_memory_pool_get_info(0x9c7fb0, 1, 0x7fff325a6748, 0x7f1200d82df4) = 0
27 ...
28 <... hsa_amd_agent_iterate_memory_pools resumed> ) = 0
29 libamdhip64.so.4->hsa_agent_get_info(0x9dbf30, 17, 0x7fff325a67e8, 0) = 0
30 <... hsa_iterate_agents resumed> ) = 0
31 libamdhip64.so.4->hsa_agent_get_info(0x9dbf30, 0, 0x7fff325a6850, 3) = 0
32 libamdhip64.so.4->hsa_agent_get_info(0x9dbf30, 0xa000, 0x9e7cd8, 0) = 0
33 libamdhip64.so.4->hsa_agent_iterate_isas(0x9dbf30, 0x7f1201720411, 0x7fff325a6760, 0x7f1201720411) = 0
34 libamdhip64.so.4->hsa_isa_get_info_alt(0x94e7c8, 0, 0x7fff325a6728, 1) = 0
35 libamdhip64.so.4->hsa_isa_get_info_alt(0x94e7c8, 1, 0x9e7f90, 0) = 0
36 libamdhip64.so.4->hsa_agent_get_info(0x9dbf30, 4, 0x9e7ce8, 0) = 0
37 ...
38 <... hsa_amd_memory_pool_allocate resumed> ) = 0
39 libamdhip64.so.4->hsa_ext_image_create(0x9dbf30, 0xa1c4c8, 0x7f10f2800000, 3 <unfinished ...>
40 libhsa-runtime64.so.1->hsaKmtAllocMemory(0, 4096, 64, 0x7fff325a6740) = 0
41 libhsa-runtime64.so.1->hsaKmtQueryPointerInfo(0x7f1202736000, 0x7fff325a65e0, 0, 0) = 0
42 libhsa-runtime64.so.1->hsaKmtMapMemoryToGPUNodes(0x7f1202736000, 4096, 0x7fff325a66e8, 0) = 0
43 <... hsa_ext_image_create resumed> ) = 0
44 libamdhip64.so.4->hsa_ext_image_destroy(0x9dbf30, 0x7f1202736000, 0x9dbf30, 0 <unfinished ...>
45 libhsa-runtime64.so.1->hsaKmtUnmapMemoryToGPU(0x7f1202736000, 0x7f1202736000, 4096, 0x9c8050) = 0
46 libhsa-runtime64.so.1->hsaKmtFreeMemory(0x7f1202736000, 4096, 0, 0) = 0
47 <... hsa_ext_image_destroy resumed> ) = 0
48 libamdhip64.so.4->hsa_amd_memory_pool_free(0x7f10f2800000, 0x7f10f2800000, 256, 0x9e76f0) = 0
49 PASSED!

Using ROCgdb

HIP developers on ROCm can use AMD's ROCgdb for debugging and profiling. ROCgdb is the ROCm source-level debugger for Linux, based on GDB, the GNU source-level debugger, equivalent of cuda-gdb, can be used with debugger frontends, such as eclipse, vscode, or gdb-dashboard. For details, see (https://github.com/ROCm-Developer-Tools/ROCgdb).

Below is a sample how to use ROCgdb run and debug HIP application, rocgdb is installed with ROCM package in the folder /opt/rocm/bin.

1 $ export PATH=$PATH:/opt/rocm/bin
2 $ rocgdb ./hipTexObjPitch
3 GNU gdb (rocm-dkms-no-npi-hipclang-6549) 10.1
4 Copyright (C) 2020 Free Software Foundation, Inc.
5 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
6 ...
7 For bug reporting instructions, please see:
8 <https://github.com/ROCm-Developer-Tools/ROCgdb/issues>.
9 Find the GDB manual and other documentation resources online at:
10  <http://www.gnu.org/software/gdb/documentation/>.
11 
12 ...
13 Reading symbols from ./hipTexObjPitch...
14 (gdb) break main
15 Breakpoint 1 at 0x4013d1: file /home/test/hip/tests/src/texture/hipTexObjPitch.cpp, line 98.
16 (gdb) run
17 Starting program: /home/test/hip/build/directed_tests/texture/hipTexObjPitch
18 [Thread debugging using libthread_db enabled]
19 Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
20 
21 Breakpoint 1, main ()
22  at /home/test/hip/tests/src/texture/hipTexObjPitch.cpp:98
23 98 texture2Dtest<float>();
24 (gdb)c

Other Debugging Tools

There are also other debugging tools available online developers can google and choose the one best suits the debugging requirements.

Debugging HIP Applications

Below is an example to show how to get useful information from the debugger while running a simple memory copy test, which caused an issue of segmentation fault.

1 test: simpleTest2<?> numElements=4194304 sizeElements=4194304 bytes
2 Segmentation fault (core dumped)
3 
4 (gdb) run
5 Starting program: /home/test/hipamd/build/directed_tests/runtimeApi/memory/hipMemcpy_simple
6 [Thread debugging using libthread_db enabled]
7 Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
8 
9 Breakpoint 1, main (argc=1, argv=0x7fffffffdea8)
10  at /home/test/hip/tests/src/runtimeApi/memory/hipMemcpy_simple.cpp:147
11 147 int main(int argc, char* argv[]) {
12 (gdb) c
13 Continuing.
14 [New Thread 0x7ffff64c4700 (LWP 146066)]
15 
16 Thread 1 "hipMemcpy_simpl" received signal SIGSEGV, Segmentation fault.
17 0x000000000020f78e in simpleTest2<float> (numElements=4194304, usePinnedHost=true)
18  at /home/test/hip/tests/src/runtimeApi/memory/hipMemcpy_simple.cpp:104
19 104 A_h1[i] = 3.14f + 1000 * i;
20 (gdb) bt
21 #0 0x000000000020f78e in simpleTest2<float> (numElements=4194304, usePinnedHost=true)
22  at /home/test/hip/tests/src/runtimeApi/memory/hipMemcpy_simple.cpp:104
23 #1 0x000000000020e96c in main (argc=<optimized out>, argv=<optimized out>)
24  at /home/test/hip/tests/src/runtimeApi/memory/hipMemcpy_simple.cpp:163
25 (gdb) info thread
26  Id Target Id Frame
27 * 1 Thread 0x7ffff64c5880 (LWP 146060) "hipMemcpy_simpl" 0x000000000020f78e in simpleTest2<float> (numElements=4194304, usePinnedHost=true)
28  at /home/test/hip/tests/src/runtimeApi/memory/hipMemcpy_simple.cpp:104
29  2 Thread 0x7ffff64c4700 (LWP 146066) "hipMemcpy_simpl" 0x00007ffff6b0850b in ioctl
30  () from /lib/x86_64-linux-gnu/libc.so.6
31 (gdb) thread 2
32 [Switching to thread 2 (Thread 0x7ffff64c4700 (LWP 146066))]
33 #0 0x00007ffff6b0850b in ioctl () from /lib/x86_64-linux-gnu/libc.so.6
34 (gdb) bt
35 #0 0x00007ffff6b0850b in ioctl () from /lib/x86_64-linux-gnu/libc.so.6
36 #1 0x00007ffff6604568 in ?? () from /opt/rocm/lib/libhsa-runtime64.so.1
37 #2 0x00007ffff65fe73a in ?? () from /opt/rocm/lib/libhsa-runtime64.so.1
38 #3 0x00007ffff659e4d6 in ?? () from /opt/rocm/lib/libhsa-runtime64.so.1
39 #4 0x00007ffff65807de in ?? () from /opt/rocm/lib/libhsa-runtime64.so.1
40 #5 0x00007ffff65932a2 in ?? () from /opt/rocm/lib/libhsa-runtime64.so.1
41 #6 0x00007ffff654f547 in ?? () from /opt/rocm/lib/libhsa-runtime64.so.1
42 #7 0x00007ffff7f76609 in start_thread () from /lib/x86_64-linux-gnu/libpthread.so.0
43 #8 0x00007ffff6b13293 in clone () from /lib/x86_64-linux-gnu/libc.so.6
44 (gdb) thread 1
45 [Switching to thread 1 (Thread 0x7ffff64c5880 (LWP 146060))]
46 #0 0x000000000020f78e in simpleTest2<float> (numElements=4194304, usePinnedHost=true)
47  at /home/test/hip/tests/src/runtimeApi/memory/hipMemcpy_simple.cpp:104
48 104 A_h1[i] = 3.14f + 1000 * i;
49 (gdb) bt
50 #0 0x000000000020f78e in simpleTest2<float> (numElements=4194304, usePinnedHost=true)
51  at /home/test/hip/tests/src/runtimeApi/memory/hipMemcpy_simple.cpp:104
52 #1 0x000000000020e96c in main (argc=<optimized out>, argv=<optimized out>)
53  at /home/test/hip/tests/src/runtimeApi/memory/hipMemcpy_simple.cpp:163
54 (gdb)
55 ...

Useful Environment Variables

HIP provides some environment variables which allow HIP, hip-clang, or HSA driver to disable some feature or optimization. These are not intended for production but can be useful diagnose synchronization problems in the application (or driver).

Some of the most useful environment variables are described here. They are supported on the ROCm path.

Kernel Enqueue Serialization

Developers can control kernel command serialization from the host using the environment variable,

AMD_SERIALIZE_KERNEL, for serializing kernel enqueue. AMD_SERIALIZE_KERNEL = 1, Wait for completion before enqueue, AMD_SERIALIZE_KERNEL = 2, Wait for completion after enqueue, AMD_SERIALIZE_KERNEL = 3, Both.

Or AMD_SERIALIZE_COPY, for serializing copies.

AMD_SERIALIZE_COPY = 1, Wait for completion before enqueue, AMD_SERIALIZE_COPY = 2, Wait for completion after enqueue, AMD_SERIALIZE_COPY = 3, Both.

So HIP runtime can wait for GPU idle before/after any GPU command depending on the environment setting.

Making Device visible

For system with multiple devices, it's possible to make only certain device(s) visible to HIP via setting environment variable, HIP_VISIBLE_DEVICES, only devices whose index is present in the sequence are visible to HIP.

For example,

1 $ HIP_VISIBLE_DEVICES=0,1

or in the application,

1 if (totalDeviceNum > 2) {
2  setenv("HIP_VISIBLE_DEVICES", "0,1,2", 1);
3  assert(getDeviceNumber(false) == 3);
4  ... ...
5 }

Dump code object

Developers can dump code object to analyze compiler related issues via setting environment variable, GPU_DUMP_CODE_OBJECT

HSA related environment variables

HSA provides some environment variables help to analyze issues in driver or hardware, for example,

HSA_ENABLE_SDMA=0 It causes host-to-device and device-to-host copies to use compute shader blit kernels rather than the dedicated DMA copy engines. Compute shader copies have low latency (typically < 5us) and can achieve approximately 80% of the bandwidth of the DMA copy engine. This environment variable is useful to isolate issues with the hardware copy engines.

HSA_ENABLE_INTERRUPT=0 Causes completion signals to be detected with memory-based polling rather than interrupts. This environment variable can be useful to diagnose interrupt storm issues in the driver.

Summary of environment variables in HIP

The following is the summary of the most useful environment variables in HIP.

Environment variable Default value Usage
AMD_LOG_LEVEL
Enable HIP log on different Level.
0 0: Disable log.
1: Enable log on error level.
2: Enable log on warning and below levels.
0x3: Enable log on information and below levels.
0x4: Decode and display AQL packets.
AMD_LOG_MASK
Enable HIP log on different Level.
0x7FFFFFFF 0x1: Log API calls.
0x02: Kernel and Copy Commands and Barriers.
0x4: Synchronization and waiting for commands to finish.
0x8: Enable log on information and below levels.
0x20: Queue commands and queue contents.
0x40:Signal creation, allocation, pool.
0x80: Locks and thread-safety code.
0x100: Copy debug.
0x200: Detailed copy debug.
0x400: Resource allocation, performance-impacting events.
0x800: Initialization and shutdown.
0x1000: Misc debug, not yet classified.
0x2000: Show raw bytes of AQL packet.
0x4000: Show code creation debug.
0x8000: More detailed command info, including barrier commands.
0x10000: Log message location.
0xFFFFFFFF: Log always even mask flag is zero.
HIP_VISIBLE_DEVICES
Only devices whose index is present in the sequence are visible to HIP.
0,1,2: Depending on the number of devices on the system.
GPU_DUMP_CODE_OBJECT
Dump code object.
0 0: Disable.
1: Enable.
AMD_SERIALIZE_KERNEL
Serialize kernel enqueue.
0 1: Wait for completion before enqueue.
2: Wait for completion after enqueue.
3: Both.
AMD_SERIALIZE_COPY
Serialize copies.
0 1: Wait for completion before enqueue.
2: Wait for completion after enqueue.
3: Both.
HIP_HOST_COHERENT
Coherent memory in hipHostMalloc.
0 0: memory is not coherent between host and GPU.
1: memory is coherent with host.
AMD_DIRECT_DISPATCH
Enable direct kernel dispatch.
1 0: Disable.
1: Enable.
GPU_MAX_HW_QUEUES
The maximum number of hardware queues allocated per device.
4 The variable controls how many independent hardware queues HIP runtime can create per process, per device. If application allocates more HIP streams than this number, then HIP runtime will reuse the same hardware queues for the new streams in round robin manner. Please note, this maximum number does not apply to either hardware queues that are created for CU masked HIP streams, or cooperative queue for HIP Cooperative Groups (there is only one single queue per device).

General Debugging Tips

1 (gdb) set env AMD_SERIALIZE_KERNEL 3