Skip to content

Commit cde169b

Browse files
authored
Make CBlas methods standalone functions to avoid using vtables (#700)
* Make CBlas methods standalone functions to avoid using vtables When testing #696, we found that adding new CBlas methods results in an ABI compatibility. This would mean that every time we add a CBlas method, we also have to rebuild spaCy. The ABI incompatibility occurs because Cython generates a vtable for cdef methods, even when the class or its methods are final. This vtable is used by the caller to look up the (address of) the methods. When methods are added, the vtable of the caller is out-of-sync when the calling code is not recompiled. This change works around this issue by making the methods of CBlas standalone functions. * Add link to PR in comments For future reference.
1 parent 0711e60 commit cde169b

2 files changed

Lines changed: 20 additions & 12 deletions

File tree

thinc/backends/cblas.pxd

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,15 @@ cdef struct BlasFuncs
1818

1919
cdef class CBlas:
2020
cdef shared_ptr[BlasFuncs] ptr
21-
cdef saxpy_ptr saxpy(self) nogil
22-
cdef sgemm_ptr sgemm(self) nogil
23-
cdef void set_saxpy(self, saxpy_ptr saxpy) nogil
24-
cdef void set_sgemm(self, sgemm_ptr sgemm) nogil
21+
22+
23+
# Note: the following functions are intentionally standalone. If we make them
24+
# methods of CBlas, Cython will generate and use a vtable. This makes it
25+
# impossible to add new BLAS functions later without breaking the ABI.
26+
#
27+
# See https://github.com/explosion/thinc/pull/700 for more information.
28+
29+
cdef saxpy_ptr saxpy(CBlas cblas) nogil
30+
cdef sgemm_ptr sgemm(CBlas cblas) nogil
31+
cdef void set_saxpy(CBlas cblas, saxpy_ptr saxpy) nogil
32+
cdef void set_sgemm(CBlas cblas, sgemm_ptr sgemm) nogil

thinc/backends/cblas.pyx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ cdef class CBlas:
1919
funcs.sgemm = blis.cy.sgemm
2020
self.ptr = make_shared[BlasFuncs](funcs)
2121

22-
cdef saxpy_ptr saxpy(self) nogil:
23-
return deref(self.ptr).saxpy
22+
cdef saxpy_ptr saxpy(CBlas cblas) nogil:
23+
return deref(cblas.ptr).saxpy
2424

25-
cdef sgemm_ptr sgemm(self) nogil:
26-
return deref(self.ptr).sgemm
25+
cdef sgemm_ptr sgemm(CBlas cblas) nogil:
26+
return deref(cblas.ptr).sgemm
2727

28-
cdef void set_saxpy(self, saxpy_ptr saxpy) nogil:
29-
deref(self.ptr).saxpy = saxpy
28+
cdef void set_saxpy(CBlas cblas, saxpy_ptr saxpy) nogil:
29+
deref(cblas.ptr).saxpy = saxpy
3030

31-
cdef void set_sgemm(self, sgemm_ptr sgemm) nogil:
32-
deref(self.ptr).sgemm = sgemm
31+
cdef void set_sgemm(CBlas cblas, sgemm_ptr sgemm) nogil:
32+
deref(cblas.ptr).sgemm = sgemm

0 commit comments

Comments
 (0)