5.3 KiB
C++ Print Debugging Utilities
Status
Implemented
Proposed by: Adam Gibson (20-11-2024) Discussed with: Paul Dubs
Context
We need a way to provide debugging utilities for C++ code in the nd4j library. These utilities help in identifying issues such as out-of-bounds crashes and unexpected behavior in mathematical operations. The goal is to have a set of tools that can be easily enabled or disabled via configuration flags.
Decision
We implement three distinct debugging utilities that can be controlled through configuration flags:
- Print Indices - For tracking loop execution and array access
- Print Math - For debugging mathematical operations
- Preprocessor Output - For debugging macro behavior
Each utility serves a specific debugging purpose and can be independently enabled or disabled through both Maven and CMake configuration.
Configuration
Maven Configuration (pom.xml)
<!-- Print Indices Configuration -->
<libnd4j.printindices>OFF</libnd4j.printindices>
<!-- Print Math Configuration -->
<libnd4j.printmath>OFF</libnd4j.printmath>
<!-- Preprocessor Configuration -->
<libnd4j.preprocess>OFF</libnd4j.preprocess>
Build System Integration
The utilities are integrated into the build system through a shell script that configures CMake. The script:
- Echoes configuration status:
echo PRINT_INDICES = "$PRINT_INDICES"
echo PRINT_MATH = "$PRINT_MATH"
echo PREPROCESS = "$PREPROCESS"
- Passes configuration to CMake:
eval "$CMAKE_COMMAND" \
-DPRINT_MATH="$PRINT_MATH" \
-DPRINT_INDICES="$PRINT_INDICES" \
# ... other CMake configurations
- Special handling for preprocessing:
if [ "$PREPROCESS" == "ON" ]; then
# Re-run CMake with preprocessing enabled
eval "$CMAKE_COMMAND" \
-DPRINT_MATH="$PRINT_MATH" \
-DPRINT_INDICES="$PRINT_INDICES" \
-DSD_PREPROCESS="$PREPROCESS" \
# ... other configurations
echo "Running preprocessing step..."
exit 0
fi
Implementation Details
1. Print Indices Utility
Purpose
Tracks loop iterations and array access patterns to help identify out-of-bounds issues and iteration-related bugs.
Build Configuration
- Set through Maven property
libnd4j.printindices - Passed to CMake as
PRINT_INDICES - Defines
PRINT_INDICESmacro in C++ code
Implementation
#if defined(PRINT_INDICES)
printf("i: %lld xEws %lld ReduceBoolFunction<X, Z>::execScalar\n", i, xEws);
#endif
Example Usage
else {
for (auto i = start; i < stop; i++) {
#if defined(PRINT_INDICES)
printf("i: %lld xEws %lld ReduceBoolFunction<X, Z>::execScalar\n", i, xEws);
#endif
intermediate[thread_id] = OpType::update(
intermediate[thread_id],
OpType::op(x[i * xEws], extraParams),
extraParams
);
}
}
2. Print Math Utility
Purpose
Provides detailed tracking of mathematical operations, including input values, outputs, and execution flow.
Build Configuration
- Set through Maven property
libnd4j.printmath - Passed to CMake as
PRINT_MATH - Defines
SD_GCC_FUNCTRACEmacro in C++ code when enabled
Implementation
template <>
SD_INLINE SD_HOST void sd_print_math2<uint16_t>(char* func_name, uint16_t input1, uint16_t input2, uint16_t output) {
#if defined(SD_GCC_FUNCTRACE)
PRINT_IF_NECESSARY(func_name);
#endif
printf("%s: input1 = %d, input2 = %d, output = %d\n", func_name, input1, input2, output);
fflush(stdout);
}
3. Preprocessor Output Utility
Purpose
Generates preprocessed source files to help debug macro-related issues and understand macro expansion.
Build Configuration
- Set through Maven property
libnd4j.preprocess - Passed to CMake as
SD_PREPROCESS - Triggers special build flow in shell script when enabled
Build Process
When preprocessing is enabled:
- Maven sets
libnd4j.preprocess=ON - Shell script detects
PREPROCESS=ON - CMake is run with
-DSD_PREPROCESS=ON - Build exits after preprocessing step
- Preprocessed files are generated in the build directory
Implementation
if("${SD_PREPROCESS}" STREQUAL "ON")
message("Preprocessing enabled ${CMAKE_BINARY_DIR}")
include_directories(${CMAKE_BINARY_DIR}/../../include)
list(REMOVE_DUPLICATES ALL_SOURCES)
# Generate preprocessed files
Consequences
Print Indices
Advantages
- Easily identifies loop boundary issues
- Helps debug array access patterns
- Minimal code overhead
Drawbacks
- Can generate large amounts of output
- Performance impact when enabled
Print Math
Advantages
- Detailed visibility into mathematical operations
- Type-safe debugging
- Stack trace integration
Drawbacks
- Increased binary size
- Runtime overhead when enabled
- Additional complexity in template code
Preprocessor Output
Advantages
- Clear visibility into macro expansion
- Helps debug complex macro interactions
- Useful for template debugging
- Early exit prevents unnecessary compilation steps
Drawbacks
- Increases build complexity
- Additional disk space requirements
- Requires separate build run for preprocessing
- Cannot be combined with normal build flow
References
- platformmath.h
- templatemath.h
- CMakeLists.txt configuration
- pom.xml configuration
- build-dl4j-natives.sh script
- ReduceBoolFunction implementation