CPU Twin Debugging

This section describes how to debug the CPU domain: kernel function verification on the CPU, GDB debugging, and printing using the printf command. Currently, the SIMT programming scenario is not supported.

During CPU debugging, configuring log-related environment variables can help you record program running processes and exceptions, and debug functions.

For details about the restrictions and description of environment variables, see Logging.

Verifying the Kernel Function on the CPU

On a non-Ascend device, you can use the CPU simulation environment to develop and test operators, and then use the Ascend device for accelerated computation after the operators are ready. In Compilation and Running, we have introduced the compilation and running of the operator kernel program in the NPU domain. Compared with the operator running logic in the NPU domain, the operator kernel program is compiled as a host program in the CPU domain. In this case, the operator kernel program is linked to the CPU debugging library, and the executable file generated after compilation is executed to verify the running of the operator in the CPU domain. The running program on the CPU is debugged step by step by using the GDB general debugging tool. This can accurately verify whether the program execution process meets the expectation.

Figure 1 Comparison of the kernel function running logic between the CPU and NPU domains

The CMake compilation mode is recommended, which can quickly enable the twin debugging function in the CPU domain with minimal modifications.

  1. To enable debugging in the CPU domain, include the cpu_debug_launch.h header file.

    In CPU debugging mode, the BiSheng compiler escapes the process of calling the kernel function using <<<>>>, implementing call of the kernel function in the CPU domain. The related call function is defined in cpu_debug_launch.h. In the source file of calling the kernel function using the <<<>>> syntax, include the required header file in the following way:
    1
    2
    3
    #ifdef ASCENDC_CPU_DEBUG
    #include "cpu_debug_launch.h"
    #endif
    

  2. Pass the variables CMAKE_ASC_RUN_MODE and CMAKE_ASC_ARCHITECTURES in the CMake configuration phase to enable CPU domain compilation. The following is a command example:

    cmake -B build -DCMAKE_ASC_RUN_MODE=cpu -DCMAKE_ASC_ARCHITECTURES=dav-2201

    cpu indicates to enable CPU domain compilation. The string following dav- is the NPU architecture version. Replace the string with the actual architecture version number.

    For details about how to configure other items in CMakeLists.txt, see Compilation Using CMake.

To unify the code in the CPU and NPU domains, the framework adapts only a proportion of ACL APIs in the CPU domain. When using the CPU domain debugging function, you can use only the following ACL APIs and cannot link the AscendCL library.

  • APIs with actual functions and callable in the CPU domain
    • aclDataTypeSize, aclFloat16ToFloat, and aclFloatToFloat16
    • aclrtMalloc, aclrtFree, aclrtMallocHost, aclrtFreeHost, aclrtMemset, aclrtMemsetAsync, aclrtMemcpy, aclrtMemcpyAsync, aclrtMemcpy2d, aclrtMemcpy2dAsync, aclrtCreateContext, and aclrtDestroyContext
  • APIs without actual functions, which are implemented through stubs
    • Profile data collection

      aclprofInit, aclprofSetConfig, aclprofStart, aclprofStop, and aclprofFinalize

    • System configuration

      aclInit, aclFinalize, and aclrtGetVersion

    • Runtime management

      aclrtSetDevice, aclrtResetDevice, aclrtCreateStream, aclrtCreateStreamWithConfig, aclrtDestroyStream, aclrtDestroyStreamForce, aclrtSynchronizeStream, aclrtCreateContext, and aclrtDestroyContext

GDB Debugging

You can use GDB to debug the operator computation precision step by step. The CPU debugging has been changed to multi-process debugging, and each core starts over an independent subprocess. Therefore, the GDB needs to be changed to the subprocess debugging mode. For the coupled architecture, each AI Core starts one subprocess. For the decoupled architecture, each AI Core starts three subprocesses (one Cube core and two Vector cores) by default.

The following is an example of commands for debugging a single subprocess:

gdb --args add_custom_cpu
set follow-fork-mode child
break add_custom.cpp:45
run
list
backtrace
print i
break add_custom.cpp:56
continue
display xLocal
quit

printf

Compile printf(...) in the code to observe the value output. The sample code is as follows:
1
2
printf("xLocal size: %d\n", xLocal.GetSize()); 
printf("tileLength: %d\n", tileLength);