Skip to content

Commit af809f3

Browse files
committed
switch to QBLAS overhaul-rewrite: new C ABI, meson subproject, sleef pre-ordered
1 parent 156edad commit af809f3

4 files changed

Lines changed: 72 additions & 130 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,4 @@ compile_commands.json
146146

147147
# docs
148148
/docs/_build/
149+
build_log.txt

src/csrc/quadblas_interface.cpp

Lines changed: 68 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -1,116 +1,85 @@
1+
/* numpy-quaddtype shim around QBLAS.
2+
*
3+
* The legacy code called the QuadBLAS:: C++ template namespace from the
4+
* pre-overhaul, header-only QBLAS. The current QBLAS (branch
5+
* `overhaul-rewrite`) exposes a stable C ABI in `qblas/qblas.h` with
6+
* CBLAS-style entry points (`cblas_qdot`, `cblas_qgemm`, …) and runtime
7+
* SIMD dispatch (sse2/avx2/avx512/neon). This file translates the
8+
* `qblas_dot` / `qblas_gemv` / `qblas_gemm` symbols that the rest of
9+
* numpy-quaddtype calls into the new CBLAS-style API. Function
10+
* signatures exposed to the rest of the package are unchanged.
11+
*/
12+
113
#include "quadblas_interface.h"
214
#include <cstring>
315
#include <algorithm>
416

517
#ifndef DISABLE_QUADBLAS
6-
#include "quadblas/quadblas.hpp"
7-
#endif // DISABLE_QUADBLAS
18+
#include <qblas/qblas.h>
19+
#endif
820

921
extern "C" {
1022

23+
#ifndef DISABLE_QUADBLAS
1124

12-
#ifndef DISABLE_QUADBLAS
25+
static inline QBLAS_LAYOUT to_layout(char c) {
26+
return (c == 'C' || c == 'c') ? QblasColMajor : QblasRowMajor;
27+
}
28+
static inline QBLAS_TRANSPOSE to_trans(char c) {
29+
if (c == 'T' || c == 't') return QblasTrans;
30+
if (c == 'C' || c == 'c') return QblasConjTrans;
31+
return QblasNoTrans;
32+
}
1333

1434
int
15-
qblas_dot(size_t n, Sleef_quad *x, size_t incx, Sleef_quad *y, size_t incy, Sleef_quad *result)
35+
qblas_dot(size_t n, Sleef_quad *x, size_t incx,
36+
Sleef_quad *y, size_t incy, Sleef_quad *result)
1637
{
1738
if (!x || !y || !result || n == 0) {
1839
return -1;
1940
}
20-
21-
try {
22-
*result = QuadBLAS::dot(n, x, incx, y, incy);
23-
return 0;
24-
}
25-
catch (...) {
26-
return -1;
27-
}
41+
*result = cblas_qdot((int)n, x, (int)incx, y, (int)incy);
42+
return 0;
2843
}
2944

3045
int
31-
qblas_gemv(char layout, char trans, size_t m, size_t n, Sleef_quad *alpha, Sleef_quad *A,
32-
size_t lda, Sleef_quad *x, size_t incx, Sleef_quad *beta, Sleef_quad *y, size_t incy)
46+
qblas_gemv(char layout, char trans, size_t m, size_t n,
47+
Sleef_quad *alpha, Sleef_quad *A, size_t lda,
48+
Sleef_quad *x, size_t incx,
49+
Sleef_quad *beta, Sleef_quad *y, size_t incy)
3350
{
3451
if (!alpha || !A || !x || !beta || !y || m == 0 || n == 0) {
3552
return -1;
3653
}
37-
38-
try {
39-
// Convert layout
40-
QuadBLAS::Layout qblas_layout;
41-
if (layout == 'R' || layout == 'r') {
42-
qblas_layout = QuadBLAS::Layout::RowMajor;
43-
}
44-
else if (layout == 'C' || layout == 'c') {
45-
qblas_layout = QuadBLAS::Layout::ColMajor;
46-
}
47-
else {
48-
return -1; // Invalid layout
49-
}
50-
51-
// Handle transpose (swap dimensions for transpose)
52-
size_t actual_m = m, actual_n = n;
53-
if (trans == 'T' || trans == 't' || trans == 'C' || trans == 'c') {
54-
std::swap(actual_m, actual_n);
55-
// For transpose, we need to adjust the layout
56-
if (qblas_layout == QuadBLAS::Layout::RowMajor) {
57-
qblas_layout = QuadBLAS::Layout::ColMajor;
58-
}
59-
else {
60-
qblas_layout = QuadBLAS::Layout::RowMajor;
61-
}
62-
}
63-
64-
// Call QBLAS GEMV
65-
QuadBLAS::gemv(qblas_layout, actual_m, actual_n, *alpha, A, lda, x, incx, *beta, y, incy);
66-
67-
return 0;
68-
}
69-
catch (...) {
70-
return -1;
71-
}
54+
cblas_qgemv(to_layout(layout), to_trans(trans),
55+
(int)m, (int)n,
56+
*alpha, A, (int)lda,
57+
x, (int)incx,
58+
*beta, y, (int)incy);
59+
return 0;
7260
}
7361

7462
int
75-
qblas_gemm(char layout, char transa, char transb, size_t m, size_t n, size_t k, Sleef_quad *alpha,
76-
Sleef_quad *A, size_t lda, Sleef_quad *B, size_t ldb, Sleef_quad *beta, Sleef_quad *C,
77-
size_t ldc)
63+
qblas_gemm(char layout, char transa, char transb,
64+
size_t m, size_t n, size_t k,
65+
Sleef_quad *alpha, Sleef_quad *A, size_t lda,
66+
Sleef_quad *B, size_t ldb,
67+
Sleef_quad *beta, Sleef_quad *C, size_t ldc)
7868
{
7969
if (!alpha || !A || !B || !beta || !C || m == 0 || n == 0 || k == 0) {
8070
return -1;
8171
}
82-
83-
try {
84-
QuadBLAS::Layout qblas_layout;
85-
if (layout == 'R' || layout == 'r') {
86-
qblas_layout = QuadBLAS::Layout::RowMajor;
87-
}
88-
else if (layout == 'C' || layout == 'c') {
89-
qblas_layout = QuadBLAS::Layout::ColMajor;
90-
}
91-
else {
92-
return -1; // Invalid layout
93-
}
94-
95-
// For now, we only support no transpose
96-
// TODO: Implement transpose support if needed
97-
if ((transa != 'N' && transa != 'n') || (transb != 'N' && transb != 'n')) {
98-
return -1; // Transpose not implemented yet
99-
}
100-
101-
QuadBLAS::gemm(qblas_layout, m, n, k, *alpha, A, lda, B, ldb, *beta, C, ldc);
102-
103-
return 0;
104-
}
105-
catch (...) {
106-
return -1;
107-
}
72+
cblas_qgemm(to_layout(layout), to_trans(transa), to_trans(transb),
73+
(int)m, (int)n, (int)k,
74+
*alpha, A, (int)lda, B, (int)ldb,
75+
*beta, C, (int)ldc);
76+
return 0;
10877
}
10978

11079
int
11180
qblas_supports_backend(QuadBackendType backend)
11281
{
113-
// QBLAS only supports SLEEF backend
82+
/* QBLAS only supports the SLEEF backend (it is built on top of SLEEF). */
11483
return (backend == BACKEND_SLEEF) ? 1 : 0;
11584
}
11685

@@ -121,113 +90,94 @@ py_quadblas_set_num_threads(PyObject *self, PyObject *args)
12190
if (!PyArg_ParseTuple(args, "i", &num_threads)) {
12291
return NULL;
12392
}
124-
12593
if (num_threads <= 0) {
12694
PyErr_SetString(PyExc_ValueError, "Number of threads must be positive");
12795
return NULL;
12896
}
129-
130-
QuadBLAS::set_num_threads(num_threads);
97+
qblas_set_num_threads(num_threads);
13198
Py_RETURN_NONE;
13299
}
133100

134101
PyObject *
135102
py_quadblas_get_num_threads(PyObject *self, PyObject *args)
136103
{
137-
int num_threads = QuadBLAS::get_num_threads();
138-
return PyLong_FromLong(num_threads);
104+
return PyLong_FromLong(qblas_get_num_threads());
139105
}
140106

141107
PyObject *
142108
py_quadblas_get_version(PyObject *self, PyObject *args)
143109
{
144-
return PyUnicode_FromString("QuadBLAS 1.0.0 - High Performance Quad Precision BLAS");
110+
/* qblas_get_version() returns "QBLAS X.Y.Z"; pair it with the
111+
* runtime-detected SIMD tier so callers can confirm what's active. */
112+
const char *ver = qblas_get_version();
113+
const char *tier = qblas_get_dispatch_tier();
114+
char buf[256];
115+
PyOS_snprintf(buf, sizeof buf, "%s (dispatch: %s)", ver, tier);
116+
return PyUnicode_FromString(buf);
145117
}
146118

147119
int
148120
_quadblas_set_num_threads(int num_threads)
149121
{
150-
QuadBLAS::set_num_threads(num_threads);
122+
qblas_set_num_threads(num_threads);
151123
return 0;
152124
}
153125

154126
int
155127
_quadblas_get_num_threads(void)
156128
{
157-
int num_threads = QuadBLAS::get_num_threads();
158-
return num_threads;
129+
return qblas_get_num_threads();
159130
}
160131

161-
#else // DISABLE_QUADBLAS
162-
132+
#else /* DISABLE_QUADBLAS */
163133

164134
int
165135
qblas_dot(size_t n, Sleef_quad *x, size_t incx, Sleef_quad *y, size_t incy, Sleef_quad *result)
166-
{
167-
return -1; // QBLAS is disabled, dot product not available
168-
}
136+
{ return -1; }
169137

170138
int
171139
qblas_gemv(char layout, char trans, size_t m, size_t n, Sleef_quad *alpha, Sleef_quad *A,
172140
size_t lda, Sleef_quad *x, size_t incx, Sleef_quad *beta, Sleef_quad *y, size_t incy)
173-
{
174-
return -1; // QBLAS is disabled, GEMV not available
175-
}
141+
{ return -1; }
176142

177143
int
178144
qblas_gemm(char layout, char transa, char transb, size_t m, size_t n, size_t k, Sleef_quad *alpha,
179145
Sleef_quad *A, size_t lda, Sleef_quad *B, size_t ldb, Sleef_quad *beta, Sleef_quad *C,
180146
size_t ldc)
181-
{
182-
return -1; // QBLAS is disabled, GEMM not available
183-
}
147+
{ return -1; }
184148

185-
int
186-
qblas_supports_backend(QuadBackendType backend)
187-
{
188-
return -1; // QBLAS is disabled, backend support not available
189-
}
149+
int qblas_supports_backend(QuadBackendType backend) { return -1; }
190150

191151
PyObject *
192152
py_quadblas_set_num_threads(PyObject *self, PyObject *args)
193153
{
194-
// raise error
195154
PyErr_SetString(PyExc_NotImplementedError, "QuadBLAS is disabled");
196155
return NULL;
197156
}
198-
199157
PyObject *
200158
py_quadblas_get_num_threads(PyObject *self, PyObject *args)
201159
{
202-
// raise error
203160
PyErr_SetString(PyExc_NotImplementedError, "QuadBLAS is disabled");
204161
return NULL;
205162
}
206-
207163
PyObject *
208164
py_quadblas_get_version(PyObject *self, PyObject *args)
209165
{
210-
// raise error
211166
PyErr_SetString(PyExc_NotImplementedError, "QuadBLAS is disabled");
212167
return NULL;
213168
}
214169

215-
int
216-
_quadblas_set_num_threads(int num_threads)
170+
int _quadblas_set_num_threads(int num_threads)
217171
{
218-
// raise error
219172
PyErr_SetString(PyExc_NotImplementedError, "QuadBLAS is disabled");
220173
return -1;
221174
}
222-
223-
int
224-
_quadblas_get_num_threads(void)
175+
int _quadblas_get_num_threads(void)
225176
{
226-
// raise error
227177
PyErr_SetString(PyExc_NotImplementedError, "QuadBLAS is disabled");
228178
return -1;
229179
}
230180

231-
#endif // DISABLE_QUADBLAS
181+
#endif /* DISABLE_QUADBLAS */
232182

233-
} // extern "C"
183+
} /* extern "C" */

subprojects/packagefiles/qblas/meson.build

Lines changed: 0 additions & 8 deletions
This file was deleted.

subprojects/qblas.wrap

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
[wrap-git]
2-
directory=qblas
3-
url=https://github.com/SwayamInSync/QBLAS.git
4-
revision=42126fd78cbc04e9b031475fe39f4f46eaa51e01
5-
patch_directory = qblas
2+
directory = qblas
3+
url = https://github.com/SwayamInSync/QBLAS.git
4+
revision = overhaul-rewrite
65

76
[provide]
87
qblas = qblas_dep

0 commit comments

Comments
 (0)