[FEA] Add CMake Option to Disable Exceptions
I'm working on a project that requires the use of the C++ compile option -fno-exceptions to optimize my library's performance and reduce binary size.
When compiling RMM with -fno-exceptions, I encountered a compilation error because code paths like RMM_EXPECT explicitly or implicitly use throw (e.g., https://github.com/rapidsai/rmm/blob/507278505eeda79436c1000da6808efa219cf3d2/cpp/include/rmm/detail/error.hpp#L65).
Could the RMM library implement a CMake option (similar to SPDLOG_NO_EXCEPTIONS in spdlog) to conditionally disable exception-throwing behavior and allow for compilation with -fno-exceptions?
@JieRen98 RMM relies on C++ exceptions to convey problems like out-of-memory errors back to applications using RMM.
What design would you propose for this? A special return value for calls that error? Ignoring errors entirely? Would you be interested in contributing a pull request after we discuss possible designs?
My project primarily involves C libraries, where I use an extern "C" wrapper to export a C API that utilizes some RMM features. These C APIs are, in turn, consumed by upstream libraries.
For my specific use case, I only require that the program prints necessary error messages and terminates upon encountering a critical error.
I would like to contribute, but I don't have a definitive proposal. Perhaps a simple approach—such as having functions return a NULL pointer (similar to malloc) on a bad allocation—would be sufficient. I don't know... What do you think?
I believe that supporting both exception-enabled and exception-disabled builds is a crucial feature. Many libraries (especially C libraries) do not support or require exception handling. By removing exception support, one can achieve a slight performance improvement and a significant reduction in binary size. What do you think?
I think you can use try { ... } catch (...) { ... } blocks in your extern "C" wrappers to put a firewall around potentially exception-throwing code.
Exceptions are a core part of RMM's C++ design, so I don't expect this to change in our C++ code. Simply ignoring exceptions would not be safe. If we added a C API for RMM, I would probably recommend that we provide error codes as a return value, rather than using null pointers to indicate an allocation failure.
Would you be interested in helping with the design of an official C API? We have had other requests for this, and I'd like to see what you are currently doing to wrap RMM in C. Is this a public project?
Yes, I agree that confining the try-catch blocks to the extern "C" wrappers would ensure the program's reliability in the current situation.
Personally, I have a strong preference for binary optimization—I typically disable exceptions and strip symbols in my projects to achieve the smallest possible executable size.
I would be happy to assist with the design and development of official C APIs and the mechanisms required to support an exception-disabled configuration.
My current work involves developing sparse direct solvers and optimizing/hijacking various runtime functions (such as those similar to cudaMalloc). Both of these projects export C APIs but are written in C++. While they are not public, I am certainly open to discussing my specific use cases with you privately.
I found this C wrapper for RMM, which is Apache-2.0 licensed. It appears to use RMM 21.10, so it's 4 years old, but it might be a good starting point for exploration.
https://github.com/DrTimothyAldenDavis/GraphBLAS/tree/1213aa68551fdfc7e3aefb981ffb91ecd98d3e79/rmm_wrap
I found this C wrapper for RMM, which is Apache-2.0 licensed. It appears to use RMM 21.10, so it's 4 years old, but it might be a good starting point for exploration.
https://github.com/DrTimothyAldenDavis/GraphBLAS/tree/1213aa68551fdfc7e3aefb981ffb91ecd98d3e79/rmm_wrap
Thanks. Prof. Tim Davis is a real legend. I am still using his SuiteSparse dataset in my recent paper. :D
After finishing my current project (December deadline), I will spend more time with the C API RMM. But we can discuss before that. GraphBLAS's RMM C API is mostly good, but I think it may be better to maintain an internal map to store the size of allocation instead of passing it to void rmm_wrap_deallocate( void *p, std::size_t size ). From my experience, C APIs like free or cudaFree do not need the size.