Skip to content

Commit 27f9d5b

Browse files
committed
Add threading support for Apple Accelerate
These APIs are new in macOS 15, but only allow saying if you want single threaded or multi-threaded operation, not specifying the actual number of threads to use in a multi-threaded setup.
1 parent 072b5f6 commit 27f9d5b

File tree

1 file changed

+38
-0
lines changed

1 file changed

+38
-0
lines changed

src/threading.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@
3131
} MKLVersion;
3232

3333

34+
/* Apple Accelerate doesn't allow setting the number of threads directly, it only has an
35+
* option to do single-threaded or multi-threaded. That is controlled via the BLASSetThreading
36+
* API introduced in macOS 15.
37+
*
38+
* These constants are from the vecLib.framework/Headers/thread_api.h file
39+
*/
40+
#define ACCELERATE_BLAS_THREADING_MULTI_THREADED 0
41+
#define ACCELERATE_BLAS_THREADING_SINGLE_THREADED 1
42+
3443
/*
3544
* We provide a flexible thread getter/setter interface here; by calling `lbt_set_num_threads()`
3645
* libblastrampoline will propagate the call through to its loaded libraries as long as the
@@ -50,6 +59,7 @@ static char * getter_names[MAX_THREADING_NAMES] = {
5059
"nvpl_lapack_get_max_threads",
5160
// We special-case MKL in the lookup loop below
5261
//"MKL_Domain_Get_Max_Threads",
62+
// We special-case Apple Accelerate below
5363
NULL
5464
};
5565

@@ -60,6 +70,7 @@ static char * setter_names[MAX_THREADING_NAMES] = {
6070
"nvpl_lapack_set_num_threads",
6171
// We special-case MKL in the lookup loop below
6272
//"MKL_Domain_Set_Num_Threads",
73+
// We special-case Apple Accelerate below
6374
NULL
6475
};
6576

@@ -129,6 +140,22 @@ LBT_DLLEXPORT int32_t lbt_get_num_threads() {
129140
}
130141
}
131142
}
143+
144+
// Special case Apple Accelerate because we have to determine if we are single-threaded or multi-threaded
145+
// This API only exists on macOS 15+.
146+
int (*fptr_acc)(void) = lookup_symbol(lib->handle, "BLASGetThreading");
147+
if (fptr != NULL) {
148+
int nthreads = fptr_acc();
149+
150+
if(nthreads == ACCELERATE_BLAS_THREADING_MULTI_THREADED) {
151+
// This number is arbitrary right now, but greater than 1 to mean multi-threaded.
152+
// TODO: Can we guestimate the number of threads from the APPLE_NTHREADS symbol in accelerate?
153+
max_threads = 2;
154+
} else {
155+
// Single-threaded
156+
max_threads = max(max_threads, 1);
157+
}
158+
}
132159
}
133160
return max_threads;
134161
}
@@ -157,5 +184,16 @@ LBT_DLLEXPORT void lbt_set_num_threads(int32_t nthreads) {
157184
fptr(nthreads, MKL_DOMAIN_BLAS);
158185
fptr(nthreads, MKL_DOMAIN_LAPACK);
159186
}
187+
188+
// Special case Apple Accelerate because we have to determine if we must set multi-threaded or single-threaded
189+
// This API only exists on macOS 15+.
190+
int (*fptr_acc)(int) = lookup_symbol(lib->handle, "BLASSetThreading");
191+
if (fptr != NULL) {
192+
if(nthreads > 1) {
193+
fptr_acc(ACCELERATE_BLAS_THREADING_MULTI_THREADED);
194+
} else {
195+
fptr_acc(ACCELERATE_BLAS_THREADING_SINGLE_THREADED);
196+
}
197+
}
160198
}
161199
}

0 commit comments

Comments
 (0)