| | | 1 | | // Copyright 2025 Digital Holography Foundation |
| | | 2 | | // |
| | | 3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
| | | 4 | | // you may not use this file except in compliance with the License. |
| | | 5 | | // You may obtain a copy of the License at |
| | | 6 | | // |
| | | 7 | | // http://www.apache.org/licenses/LICENSE-2.0 |
| | | 8 | | // |
| | | 9 | | // Unless required by applicable law or agreed to in writing, software |
| | | 10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
| | | 11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| | | 12 | | // See the License for the specific language governing permissions and |
| | | 13 | | // limitations under the License. |
| | | 14 | | |
| | | 15 | | #include "curaii/cusolver.hh" |
| | | 16 | | |
| | | 17 | | #include <format> |
| | | 18 | | |
| | | 19 | | #include "logger.hh" |
| | | 20 | | |
| | | 21 | | namespace { |
| | | 22 | | |
| | 0 | 23 | | const char *cusolverGetErrorString(cusolverStatus_t status) { |
| | 0 | 24 | | switch (status) { |
| | | 25 | | case CUSOLVER_STATUS_SUCCESS: |
| | 0 | 26 | | return "The operation completed successfully"; |
| | | 27 | | case CUSOLVER_STATUS_NOT_INITIALIZED: |
| | 0 | 28 | | return "Library not initialized"; |
| | | 29 | | case CUSOLVER_STATUS_ALLOC_FAILED: |
| | 0 | 30 | | return "Resource allocation failed"; |
| | | 31 | | case CUSOLVER_STATUS_INVALID_VALUE: |
| | 0 | 32 | | return "Invalid value"; |
| | | 33 | | case CUSOLVER_STATUS_ARCH_MISMATCH: |
| | 0 | 34 | | return "Architecture mismatch"; |
| | | 35 | | case CUSOLVER_STATUS_EXECUTION_FAILED: |
| | 0 | 36 | | return "Execution failed"; |
| | | 37 | | case CUSOLVER_STATUS_INTERNAL_ERROR: |
| | 0 | 38 | | return "Internal error"; |
| | | 39 | | case CUSOLVER_STATUS_MATRIX_TYPE_NOT_SUPPORTED: |
| | 0 | 40 | | return "Matrix type not supported"; |
| | | 41 | | case CUSOLVER_STATUS_NOT_SUPPORTED: |
| | 0 | 42 | | return "Operation not supported"; |
| | | 43 | | case CUSOLVER_STATUS_ZERO_PIVOT: |
| | 0 | 44 | | return "Zero pivot"; |
| | | 45 | | case CUSOLVER_STATUS_INVALID_LICENSE: |
| | 0 | 46 | | return "Invalid license"; |
| | | 47 | | default: |
| | 0 | 48 | | return "Unknown error"; |
| | | 49 | | } |
| | 0 | 50 | | } |
| | | 51 | | |
| | | 52 | | } // namespace |
| | | 53 | | |
| | | 54 | | namespace curaii { |
| | | 55 | | |
| | | 56 | | CusolverError::CusolverError(cusolverStatus_t code, const char *what, const char *file, int line) |
| | 0 | 57 | | : std::runtime_error(CusolverError::make_message(code, what, file, line)), code_(code) {} |
| | | 58 | | |
| | | 59 | | std::string CusolverError::make_message(cusolverStatus_t code, const char *what, const char *file, |
| | 0 | 60 | | int line) { |
| | 0 | 61 | | return std::format("cuSOLVER error: {} ({})\n expression : {}\n location : {}:{}", |
| | | 62 | | cusolverGetErrorString(code), static_cast<int>(code), what, file, line); |
| | 0 | 63 | | } |
| | | 64 | | |
| | 0 | 65 | | cusolverStatus_t CusolverError::code() const noexcept { return code_; } |
| | | 66 | | |
| | 1 | 67 | | CusolverDnHandle::CusolverDnHandle() { CUSOLVER_CHECK(cusolverDnCreate(&handle_)); } |
| | | 68 | | |
| | 1 | 69 | | CusolverDnHandle::~CusolverDnHandle() noexcept { |
| | 1 | 70 | | if (handle_) { |
| | 1 | 71 | | CUSOLVER_CHECK_NT(cusolverDnDestroy(handle_)); |
| | | 72 | | } |
| | 1 | 73 | | } |
| | | 74 | | |
| | 0 | 75 | | CusolverDnHandle::CusolverDnHandle(CusolverDnHandle &&other) noexcept : handle_(other.handle_) { |
| | 0 | 76 | | other.handle_ = nullptr; |
| | 0 | 77 | | } |
| | | 78 | | |
| | 0 | 79 | | CusolverDnHandle &CusolverDnHandle::operator=(CusolverDnHandle &&other) noexcept { |
| | 0 | 80 | | if (this != &other) { |
| | 0 | 81 | | reset(); |
| | 0 | 82 | | handle_ = other.handle_; |
| | 0 | 83 | | other.handle_ = nullptr; |
| | | 84 | | } |
| | 0 | 85 | | return *this; |
| | 0 | 86 | | } |
| | | 87 | | |
| | 1 | 88 | | cusolverDnHandle_t CusolverDnHandle::get() const noexcept { return handle_; } |
| | | 89 | | |
| | 0 | 90 | | cusolverDnHandle_t CusolverDnHandle::release() noexcept { |
| | 0 | 91 | | cusolverDnHandle_t tmp = handle_; |
| | 0 | 92 | | handle_ = nullptr; |
| | 0 | 93 | | return tmp; |
| | 0 | 94 | | } |
| | | 95 | | |
| | 0 | 96 | | void CusolverDnHandle::reset(cusolverDnHandle_t handle) noexcept { |
| | 0 | 97 | | if (handle_ != handle) { |
| | 0 | 98 | | if (handle_) { |
| | 0 | 99 | | CUSOLVER_CHECK_NT(cusolverDnDestroy(handle_)); |
| | | 100 | | } |
| | 0 | 101 | | handle_ = handle; |
| | | 102 | | } |
| | 0 | 103 | | } |
| | | 104 | | |
| | 0 | 105 | | CusolverDnHandle::operator bool() const noexcept { return handle_ != nullptr; } |
| | | 106 | | |
| | 1 | 107 | | CusolverDnParams::CusolverDnParams() { CUSOLVER_CHECK(cusolverDnCreateParams(¶ms_)); } |
| | | 108 | | |
| | 1 | 109 | | CusolverDnParams::~CusolverDnParams() noexcept { |
| | 1 | 110 | | if (params_) { |
| | 1 | 111 | | CUSOLVER_CHECK_NT(cusolverDnDestroyParams(params_)); |
| | | 112 | | } |
| | 1 | 113 | | } |
| | | 114 | | |
| | 0 | 115 | | CusolverDnParams::CusolverDnParams(CusolverDnParams &&other) noexcept : params_(other.params_) { |
| | 0 | 116 | | other.params_ = nullptr; |
| | 0 | 117 | | } |
| | | 118 | | |
| | 0 | 119 | | CusolverDnParams &CusolverDnParams::operator=(CusolverDnParams &&other) noexcept { |
| | 0 | 120 | | if (this != &other) { |
| | 0 | 121 | | reset(); |
| | 0 | 122 | | params_ = other.params_; |
| | 0 | 123 | | other.params_ = nullptr; |
| | | 124 | | } |
| | 0 | 125 | | return *this; |
| | 0 | 126 | | } |
| | | 127 | | |
| | 1 | 128 | | cusolverDnParams_t CusolverDnParams::get() const noexcept { return params_; } |
| | | 129 | | |
| | 0 | 130 | | cusolverDnParams_t CusolverDnParams::release() noexcept { |
| | 0 | 131 | | cusolverDnParams_t tmp = params_; |
| | 0 | 132 | | params_ = nullptr; |
| | 0 | 133 | | return tmp; |
| | 0 | 134 | | } |
| | | 135 | | |
| | 0 | 136 | | void CusolverDnParams::reset(cusolverDnParams_t params) noexcept { |
| | 0 | 137 | | if (params_ != params) { |
| | 0 | 138 | | if (params_) { |
| | 0 | 139 | | CUSOLVER_CHECK_NT(cusolverDnDestroyParams(params_)); |
| | | 140 | | } |
| | 0 | 141 | | params_ = params; |
| | | 142 | | } |
| | 0 | 143 | | } |
| | | 144 | | |
| | 0 | 145 | | CusolverDnParams::operator bool() const noexcept { return params_ != nullptr; } |
| | | 146 | | |
| | | 147 | | } // namespace curaii |
| | | 148 | | |
| | | 149 | | namespace curaii::detail { |
| | | 150 | | |
| | | 151 | | void log_cusolver_failure(spdlog::level::level_enum level, cusolverStatus_t code, const char *what, |
| | 0 | 152 | | const char *file, int line) { |
| | 0 | 153 | | logger()->log(level, "cuSOLVER error: {} ({})\n expression : {}\n location : {}:{}", |
| | | 154 | | cusolverGetErrorString(code), static_cast<int>(code), what, file, line); |
| | 0 | 155 | | } |
| | | 156 | | |
| | | 157 | | } // namespace curaii::detail |