src/api/native_tensor_core.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "native_tensor_decl.h" | ||
| 2 | #include "api_internal.h" | ||
| 3 | #include <vector> | ||
| 4 | |||
| 5 | using namespace brotensor::api; | ||
| 6 | |||
| 7 | namespace { | ||
| 8 | thread_local std::vector<float> tl_download_f32; | ||
| 9 | thread_local std::vector<uint16_t> tl_download_u16; | ||
| 10 | thread_local std::vector<int8_t> tl_download_i8; | ||
| 11 | } // namespace | ||
| 12 | |||
| 13 | extern "C" { | ||
| 14 | |||
| 15 | ✗ | void* bro_tensor_GpuTensor_ctor(void) { | |
| 16 | ✗ | return new GpuTensorHandle(); | |
| 17 | } | ||
| 18 | |||
| 19 | 867 | void bro_tensor_GpuTensor_dtor(void* self) { | |
| 20 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 867 times.
|
867 | delete static_cast<GpuTensorHandle*>(self); |
| 21 | 867 | } | |
| 22 | |||
| 23 | 1724 | void* bro_tensor_createTensor(int32_t rows, int32_t cols, const char* dtype) { | |
| 24 | 1724 | auto* h = new GpuTensorHandle(); | |
| 25 | 1724 | auto dt = parseDtype(dtype); | |
| 26 |
3/4✓ Branch 0 taken 1722 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1722 times.
|
1724 | if (rows > 0 && cols > 0) { |
| 27 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1722 times.
|
1722 | if (static_cast<int64_t>(rows) * cols > INT32_MAX) { |
| 28 | ✗ | setError("createTensor: rows*cols exceeds 2^31-1 elements"); | |
| 29 | ✗ | return h; | |
| 30 | } | ||
| 31 | BROTENSOR_API_TRY | ||
| 32 |
2/4✓ Branch 0 taken 1722 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1722 times.
✗ Branch 3 not taken.
|
1722 | h->tensor = brotensor::Tensor::zeros_on(brotensor::default_device(), rows, cols, dt); |
| 33 |
0/12✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
1722 | BROTENSOR_API_CATCH("createTensor") |
| 34 | 1722 | } | |
| 35 | 1724 | return h; | |
| 36 | 1724 | } | |
| 37 | |||
| 38 | 160 | int32_t bro_tensor_GpuTensor_rows_get(void* self) { | |
| 39 | 160 | auto* t = toTensor(self); | |
| 40 |
1/2✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
|
160 | return t ? t->rows : 0; |
| 41 | } | ||
| 42 | |||
| 43 | 164 | int32_t bro_tensor_GpuTensor_cols_get(void* self) { | |
| 44 | 164 | auto* t = toTensor(self); | |
| 45 |
1/2✓ Branch 0 taken 164 times.
✗ Branch 1 not taken.
|
164 | return t ? t->cols : 0; |
| 46 | } | ||
| 47 | |||
| 48 | 14 | int32_t bro_tensor_GpuTensor_size_get(void* self) { | |
| 49 | 14 | auto* t = toTensor(self); | |
| 50 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | return t ? t->size() : 0; |
| 51 | } | ||
| 52 | |||
| 53 | ✗ | int32_t bro_tensor_GpuTensor_bytes_get(void* self) { | |
| 54 | ✗ | auto* t = toTensor(self); | |
| 55 | ✗ | return t ? static_cast<int32_t>(t->bytes()) : 0; | |
| 56 | } | ||
| 57 | |||
| 58 | 10 | void bro_tensor_GpuTensor_zero(void* self) { | |
| 59 | 10 | auto* t = toTensor(self); | |
| 60 |
2/4✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
|
10 | if (t && !t->empty()) { |
| 61 | BROTENSOR_API_TRY | ||
| 62 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | t->zero(); |
| 63 |
0/12✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
10 | BROTENSOR_API_CATCH("zero") |
| 64 | 10 | } | |
| 65 | 10 | } | |
| 66 | |||
| 67 | 4 | void bro_tensor_GpuTensor_resize(void* self, int32_t rows, int32_t cols, const char* dtype) { | |
| 68 | 4 | auto* t = toTensor(self); | |
| 69 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if (!t) return; |
| 70 | 4 | auto dt = parseDtype(dtype); | |
| 71 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
4 | if (rows < 0 || cols < 0) { |
| 72 | ✗ | setError("resize: negative dimension"); | |
| 73 | ✗ | return; | |
| 74 | } | ||
| 75 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (static_cast<int64_t>(rows) * cols > INT32_MAX) { |
| 76 | ✗ | setError("resize: rows*cols exceeds 2^31-1 elements"); | |
| 77 | ✗ | return; | |
| 78 | } | ||
| 79 | BROTENSOR_API_TRY | ||
| 80 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | t->resize(rows, cols, dt); |
| 81 |
0/12✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
4 | BROTENSOR_API_CATCH("resize") |
| 82 | 4 | } | |
| 83 | |||
| 84 | 34 | const char* bro_tensor_GpuTensor_dtype(void* self) { | |
| 85 | 34 | auto* t = toTensor(self); | |
| 86 |
1/2✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
|
34 | return t ? dtypeToString(t->dtype) : "fp32"; |
| 87 | } | ||
| 88 | |||
| 89 | 2 | void* bro_tensor_GpuTensor_clone(void* self) { | |
| 90 | 2 | auto* h = new GpuTensorHandle(); | |
| 91 | 2 | auto* src = toHandle(self); | |
| 92 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (src) { |
| 93 | BROTENSOR_API_TRY | ||
| 94 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | h->tensor = src->tensor.clone(); |
| 95 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | h->shape = src->shape; |
| 96 |
0/12✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
2 | BROTENSOR_API_CATCH("clone") |
| 97 | 2 | } | |
| 98 | 2 | return h; | |
| 99 | ✗ | } | |
| 100 | |||
| 101 | // upload keeps the tensor's (rows, cols) when the data fills it exactly and | ||
| 102 | // otherwise becomes a (data_len, 1) column. | ||
| 103 | 818 | static bool uploadShape(const char* label, const brotensor::Tensor* t, uint32_t data_len, int& r, int& c) { | |
| 104 |
1/2✓ Branch 0 taken 818 times.
✗ Branch 1 not taken.
|
818 | if (data_len > static_cast<uint32_t>(INT32_MAX)) { |
| 105 | ✗ | setError(std::string(label) + ": more than 2^31-1 elements"); | |
| 106 | ✗ | return false; | |
| 107 | } | ||
| 108 | 818 | r = t->rows; | |
| 109 | 818 | c = t->cols; | |
| 110 |
1/2✓ Branch 0 taken 818 times.
✗ Branch 1 not taken.
|
818 | if (static_cast<int64_t>(r) * c != static_cast<int64_t>(data_len)) { |
| 111 | ✗ | r = static_cast<int>(data_len); | |
| 112 | ✗ | c = 1; | |
| 113 | ✗ | } | |
| 114 | 818 | return true; | |
| 115 | 818 | } | |
| 116 | |||
| 117 | 800 | void bro_tensor_GpuTensor_upload(void* self, const float* data, uint32_t data_len) { | |
| 118 | 800 | auto* t = toTensor(self); | |
| 119 |
2/4✓ Branch 0 taken 800 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 800 times.
|
800 | if (!t || !data) return; |
| 120 | 800 | int r = 0, c = 0; | |
| 121 |
1/2✓ Branch 0 taken 800 times.
✗ Branch 1 not taken.
|
800 | if (!uploadShape("upload", t, data_len, r, c)) return; |
| 122 | BROTENSOR_API_TRY | ||
| 123 |
2/4✓ Branch 0 taken 800 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 800 times.
✗ Branch 3 not taken.
|
800 | *t = brotensor::Tensor::from_host_on(brotensor::default_device(), data, r, c); |
| 124 |
0/12✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
800 | BROTENSOR_API_CATCH("upload") |
| 125 | 800 | } | |
| 126 | |||
| 127 | 608 | void bro_tensor_GpuTensor_download(void* self, bronze_native_buffer* out) { | |
| 128 |
1/2✓ Branch 0 taken 608 times.
✗ Branch 1 not taken.
|
608 | if (!out) return; |
| 129 | 608 | auto* t = toTensor(self); | |
| 130 |
2/4✓ Branch 0 taken 608 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 608 times.
|
608 | if (!t || t->empty()) { |
| 131 | ✗ | out->data = nullptr; | |
| 132 | ✗ | out->length = 0; | |
| 133 | ✗ | out->release = nullptr; | |
| 134 | ✗ | out->ctx = nullptr; | |
| 135 | ✗ | return; | |
| 136 | } | ||
| 137 |
2/2✓ Branch 0 taken 78 times.
✓ Branch 1 taken 530 times.
|
608 | if (t->dtype == brotensor::Dtype::FP32) { |
| 138 | 530 | tl_download_f32.resize(static_cast<size_t>(t->size())); | |
| 139 | 530 | t->copy_to_host(tl_download_f32.data()); | |
| 140 | 530 | out->data = tl_download_f32.data(); | |
| 141 | 530 | out->length = static_cast<uint32_t>(tl_download_f32.size()); | |
| 142 | 530 | } else { | |
| 143 | // Convert on the host: the scratch tensor must live on the CPU too, | ||
| 144 | // or cast() sees a mixed-device pair (Tensor::empty follows the | ||
| 145 | // default device, CUDA once the backend is up). | ||
| 146 | try { | ||
| 147 |
1/2✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
|
78 | auto host_t = t->to(brotensor::Device::CPU); |
| 148 |
1/2✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
|
78 | brotensor::Tensor fp32_t = brotensor::Tensor::empty_on(brotensor::Device::CPU, t->rows, t->cols, brotensor::Dtype::FP32); |
| 149 |
1/2✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
|
78 | brotensor::cast(host_t, fp32_t, brotensor::Dtype::FP32); |
| 150 |
2/4✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 78 times.
✗ Branch 3 not taken.
|
78 | tl_download_f32.resize(static_cast<size_t>(fp32_t.size())); |
| 151 |
1/2✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
|
78 | fp32_t.copy_to_host(tl_download_f32.data()); |
| 152 |
0/2✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
78 | } catch (const std::exception& e) { |
| 153 | ✗ | tl_download_f32.clear(); | |
| 154 | ✗ | setError(std::string("download: ") + e.what()); | |
| 155 | ✗ | } | |
| 156 | 78 | out->data = tl_download_f32.data(); | |
| 157 | 78 | out->length = static_cast<uint32_t>(tl_download_f32.size()); | |
| 158 | } | ||
| 159 | 608 | out->release = nullptr; | |
| 160 | 608 | out->ctx = nullptr; | |
| 161 | 608 | } | |
| 162 | |||
| 163 | ✗ | void bro_tensor_GpuTensor_uploadFp16(void* self, const uint16_t* data, uint32_t data_len) { | |
| 164 | ✗ | auto* t = toTensor(self); | |
| 165 | ✗ | if (!t || !data) return; | |
| 166 | ✗ | int r = 0, c = 0; | |
| 167 | ✗ | if (!uploadShape("uploadFp16", t, data_len, r, c)) return; | |
| 168 | BROTENSOR_API_TRY | ||
| 169 | ✗ | *t = brotensor::Tensor::from_host_fp16_on(brotensor::default_device(), data, r, c); | |
| 170 | ✗ | BROTENSOR_API_CATCH("uploadFp16") | |
| 171 | ✗ | } | |
| 172 | |||
| 173 | 18 | void bro_tensor_GpuTensor_downloadFp16(void* self, bronze_native_buffer* out) { | |
| 174 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | if (!out) return; |
| 175 | 18 | auto* t = toTensor(self); | |
| 176 |
2/4✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
|
18 | if (!t || t->empty()) { |
| 177 | ✗ | out->data = nullptr; | |
| 178 | ✗ | out->length = 0; | |
| 179 | ✗ | out->release = nullptr; | |
| 180 | ✗ | out->ctx = nullptr; | |
| 181 | ✗ | return; | |
| 182 | } | ||
| 183 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | if (t->dtype == brotensor::Dtype::FP16) { |
| 184 | 18 | tl_download_u16.resize(static_cast<size_t>(t->size())); | |
| 185 | 18 | t->copy_to_host_fp16(tl_download_u16.data()); | |
| 186 | 18 | out->data = tl_download_u16.data(); | |
| 187 | 18 | out->length = static_cast<uint32_t>(tl_download_u16.size()); | |
| 188 | 18 | } else { | |
| 189 | try { | ||
| 190 | ✗ | auto host_t = t->to(brotensor::Device::CPU); | |
| 191 | ✗ | brotensor::Tensor fp16_t = brotensor::Tensor::empty_on(brotensor::Device::CPU, t->rows, t->cols, brotensor::Dtype::FP16); | |
| 192 | ✗ | brotensor::cast(host_t, fp16_t, brotensor::Dtype::FP16); | |
| 193 | ✗ | tl_download_u16.resize(static_cast<size_t>(fp16_t.size())); | |
| 194 | ✗ | fp16_t.copy_to_host_fp16(tl_download_u16.data()); | |
| 195 | ✗ | } catch (const std::exception& e) { | |
| 196 | ✗ | tl_download_u16.clear(); | |
| 197 | ✗ | setError(std::string("downloadFp16: ") + e.what()); | |
| 198 | ✗ | } | |
| 199 | ✗ | out->data = tl_download_u16.data(); | |
| 200 | ✗ | out->length = static_cast<uint32_t>(tl_download_u16.size()); | |
| 201 | } | ||
| 202 | 18 | out->release = nullptr; | |
| 203 | 18 | out->ctx = nullptr; | |
| 204 | 18 | } | |
| 205 | |||
| 206 | 18 | void bro_tensor_GpuTensor_uploadInt8(void* self, const int8_t* data, uint32_t data_len) { | |
| 207 | 18 | auto* t = toTensor(self); | |
| 208 |
2/4✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
|
18 | if (!t || !data) return; |
| 209 | 18 | int r = 0, c = 0; | |
| 210 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | if (!uploadShape("uploadInt8", t, data_len, r, c)) return; |
| 211 | BROTENSOR_API_TRY | ||
| 212 |
2/4✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
|
18 | *t = brotensor::Tensor::from_host_int8_on(brotensor::default_device(), data, r, c); |
| 213 |
0/12✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
18 | BROTENSOR_API_CATCH("uploadInt8") |
| 214 | 18 | } | |
| 215 | |||
| 216 | 2 | void bro_tensor_GpuTensor_downloadInt8(void* self, bronze_native_buffer* out) { | |
| 217 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (!out) return; |
| 218 | 2 | auto* t = toTensor(self); | |
| 219 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
|
2 | if (!t || t->empty()) { |
| 220 | ✗ | out->data = nullptr; | |
| 221 | ✗ | out->length = 0; | |
| 222 | ✗ | out->release = nullptr; | |
| 223 | ✗ | out->ctx = nullptr; | |
| 224 | ✗ | return; | |
| 225 | } | ||
| 226 | try { | ||
| 227 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | auto host_t = t->to(brotensor::Device::CPU); |
| 228 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | tl_download_i8.resize(host_t.bytes()); |
| 229 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | std::memcpy(tl_download_i8.data(), host_t.host_raw(), host_t.bytes()); |
| 230 |
0/2✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
2 | } catch (const std::exception& e) { |
| 231 | ✗ | tl_download_i8.clear(); | |
| 232 | ✗ | setError(std::string("downloadInt8: ") + e.what()); | |
| 233 | ✗ | } | |
| 234 | 2 | out->data = tl_download_i8.data(); | |
| 235 | 2 | out->length = static_cast<uint32_t>(tl_download_i8.size()); | |
| 236 | 2 | out->release = nullptr; | |
| 237 | 2 | out->ctx = nullptr; | |
| 238 | 2 | } | |
| 239 | |||
| 240 | 4 | bool bro_tensor_GpuTensor_downloadInto(void* self, float* dst, uint32_t dst_len) { | |
| 241 | 4 | auto* t = toTensor(self); | |
| 242 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
4 | if (!t || !dst) { |
| 243 | ✗ | setError("download(dst): not a GpuTensor"); | |
| 244 | ✗ | return false; | |
| 245 | } | ||
| 246 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (t->empty()) return true; |
| 247 | 4 | const auto n = static_cast<size_t>(t->size()); | |
| 248 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (dst_len < n) { |
| 249 | ✗ | setError("download(dst): dst holds " + std::to_string(dst_len) + " elements, tensor has " + std::to_string(n)); | |
| 250 | ✗ | return false; | |
| 251 | } | ||
| 252 | BROTENSOR_API_TRY | ||
| 253 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if (t->dtype == brotensor::Dtype::FP32) { |
| 254 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | t->copy_to_host(dst); |
| 255 | 4 | } else { | |
| 256 | ✗ | auto host_t = t->to(brotensor::Device::CPU); | |
| 257 | ✗ | brotensor::Tensor fp32_t = brotensor::Tensor::empty_on(brotensor::Device::CPU, t->rows, t->cols, brotensor::Dtype::FP32); | |
| 258 | ✗ | brotensor::cast(host_t, fp32_t, brotensor::Dtype::FP32); | |
| 259 | ✗ | fp32_t.copy_to_host(dst); | |
| 260 | ✗ | } | |
| 261 | 4 | return true; | |
| 262 | ✗ | BROTENSOR_API_CATCH("download(dst)") | |
| 263 | ✗ | return false; | |
| 264 | 4 | } | |
| 265 | |||
| 266 | 4240 | const char* bro_tensor_takeError(void) { | |
| 267 | // The slot keeps the string alive until the next failure; the runtime | ||
| 268 | // copies a `str` return into a JS string before anything else runs. | ||
| 269 |
2/2✓ Branch 0 taken 4238 times.
✓ Branch 1 taken 2 times.
|
4240 | static thread_local std::string taken; |
| 270 | 4240 | taken.swap(lastErrorSlot()); | |
| 271 | 4240 | lastErrorSlot().clear(); | |
| 272 | 4240 | return taken.c_str(); | |
| 273 | } | ||
| 274 | |||
| 275 | 3452 | bool bro_tensor_available_get(void) { | |
| 276 | 3452 | return true; | |
| 277 | } | ||
| 278 | |||
| 279 | // The old binding published a lowercase identifier ("cuda" | "metal" | | ||
| 280 | // "unknown"), and everything written against bro.tensor compares against one: | ||
| 281 | // js/tensor.js falls back to "cpu", the docs spell the values lowercase and | ||
| 282 | // every caller gates with `backend === "cpu"` / `!== "cpu"`. device_name() | ||
| 283 | // answers a display name ("CPU", "CUDA", "Metal", "CUDA:1"), so lower-case it | ||
| 284 | // here rather than hand JS a string no gate can match. | ||
| 285 | 40 | const char* bro_tensor_backend_get(void) { | |
| 286 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 2 times.
|
40 | static thread_local std::string name; |
| 287 | 40 | name = brotensor::device_name(brotensor::default_device()); | |
| 288 |
2/2✓ Branch 0 taken 40 times.
✓ Branch 1 taken 200 times.
|
240 | for (char& c : name) { |
| 289 |
3/4✓ Branch 0 taken 200 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 160 times.
✓ Branch 3 taken 40 times.
|
200 | if (c >= 'A' && c <= 'Z') c = static_cast<char>(c + 32); |
| 290 | } | ||
| 291 | 40 | return name.c_str(); | |
| 292 | } | ||
| 293 | |||
| 294 | ✗ | void bro_tensor_init(void) { | |
| 295 | BROTENSOR_API_TRY | ||
| 296 | ✗ | brotensor::init(); | |
| 297 | ✗ | BROTENSOR_API_CATCH("init") | |
| 298 | ✗ | } | |
| 299 | |||
| 300 | ✗ | void bro_tensor_sync(void) { | |
| 301 | BROTENSOR_API_TRY | ||
| 302 | ✗ | brotensor::sync_all(); | |
| 303 | ✗ | BROTENSOR_API_CATCH("sync") | |
| 304 | ✗ | } | |
| 305 | |||
| 306 | } // extern "C" | ||
| 307 |