|
| 1 | +.. _debugging: |
| 2 | + |
| 3 | +Debugging |
| 4 | +######### |
| 5 | + |
| 6 | +MatX employs several tools for debugging and improving the correctness of the code. |
| 7 | + |
| 8 | +Logging |
| 9 | +-------- |
| 10 | + |
| 11 | +MatX provides a logging system that can be used to log messages to the console. This is useful for debugging your code and can be used to trace the execution of your code. |
| 12 | + |
| 13 | +See :ref:`logging_basics` for more information on the logging system. |
| 14 | + |
| 15 | +Compile Time |
| 16 | +------------ |
| 17 | + |
| 18 | +At compile time MatX uses `static_assert` calls where possible to provide helpful error messages. Static assertions have a limitation that |
| 19 | +they cannot display a formatted string, so the value of the invalid parameters are not displayed. Common compile time errors include: |
| 20 | + |
| 21 | +- Invalid rank |
| 22 | +- Invalid type |
| 23 | +- Invalid tensor shapes (for static tensor sizes) |
| 24 | + |
| 25 | +Runtime |
| 26 | +------- |
| 27 | + |
| 28 | +At runtime MatX uses C++ exceptions to throw errors. These errors are typically based on expected vs actual outcomes. Several macros are used |
| 29 | +to raise these errors: |
| 30 | + |
| 31 | +- MATX_ASSERT (boolean assertion) |
| 32 | +- MATX_ASSERT_STR (boolean assertion with a formatted string) |
| 33 | +- MATX_ASSERT_STR_EXP (boolean assertion with a formatted string and an expected value) |
| 34 | + |
| 35 | +These macros are also listed in order of usefulness with the `MATX_ASSERT_STR_EXP` macro providing the most information to the user. Common |
| 36 | +runtime errors include: |
| 37 | + |
| 38 | +- Invalid sizes |
| 39 | +- Invalid indexing |
| 40 | +- Errors returned from CUDA APIs |
| 41 | + |
| 42 | + |
| 43 | +Null Pointer Checking |
| 44 | +--------------------- |
| 45 | + |
| 46 | +Tensors in MatX may be left unitialized on declaration. This is common when a tensor is used as a class member and is not initialized in the constructor. For example: |
| 47 | + |
| 48 | +.. code-block:: cpp |
| 49 | +
|
| 50 | + class MyClass { |
| 51 | + public: |
| 52 | + MyClass() { |
| 53 | + } |
| 54 | + private: |
| 55 | + tensor_t<float> t; // Uninitialized |
| 56 | + }; |
| 57 | +
|
| 58 | +Typically `make_tensor` is used at a later time to declare the shape allocate the memory backing the tensor. Detecting an unitialized tensor on the device |
| 59 | +has a non-zero performance penalty and is disabled by default. To detect an unitialized tensor on the device, build your application in debug mode with the |
| 60 | +`NDEBUG` flag undefined. When the `NDEBUG` flag is undefined, MatX will check for unitialized tensors on the device and assert if one is found. |
| 61 | + |
| 62 | +Unsafe Aliased Memory Checking |
| 63 | +------------------------------ |
| 64 | + |
| 65 | +MatX provides an imperfect unsafe aliased memory checking system that can be used to detect when an input tensor may overlap with output tensor memory, |
| 66 | +causing a data race. The word *unsafe* is used here because there are cases where aliasing is safe, such as a direct element-wise operation. |
| 67 | +To have a false positive rate of 0 we would need to check every possible input and output location to see if any of them overlap. |
| 68 | +This would be impractical for most applications. Instead, we use several checks that can catch the most common cases of memory aliasing. Since aliasing can be |
| 69 | +an expensive check and it's not perfect, alias checking must be explicitly enabled with the CMake option `MATX_EN_UNSAFE_ALIAS_DETECTION` or the compiler |
| 70 | +define with the same name. |
| 71 | + |
| 72 | +The types of aliasing that can be detected are: |
| 73 | + |
| 74 | +- Safe element-wise aliasing: (a = a + a) // No aliasing since it's a direct element-wise operation |
| 75 | +- Safe element-wise aliasing: (slice(a, {0}, {5}) = slice(a, {0}, {5}) - slice(a, {0}, {5})) // No aliasing since it's a direct element-wise operation |
| 76 | +- Unsafe element-wise aliasing: (slice(a, {0}, {5}) = slice(a, {3}, {8}) - slice(a, {0}, {5})) // Unsafe since inputs and outputs overlap to different locations |
| 77 | +- Unsafe matrix multiplication: (c = matmul(c, d)) // Unsafe since matmul doesn't allow aliasing on input and output memory |
| 78 | +- Safe FFT: (c = fft(c)) // No aliasing since FFT allows aliasing |
| 79 | +- False positive: (slice(a, {0}, {6}, {2}) = slice(a, {0}, {6}, {2}) + slice(a, {0}, {6}, {2})) // Non-unity strides throw false positive currently |
0 commit comments