Skip to content

Add MKLMemory class to expose MKL allocated memory via Python buffer protocol - #182

Open
ndgrigorian wants to merge 12 commits into
masterfrom
feature/add-mkl-memory
Open

Add MKLMemory class to expose MKL allocated memory via Python buffer protocol#182
ndgrigorian wants to merge 12 commits into
masterfrom
feature/add-mkl-memory

Conversation

@ndgrigorian

@ndgrigorian ndgrigorian commented Apr 12, 2026

Copy link
Copy Markdown
Collaborator

This PR proposes the introduction of _mkl_memory.pyx, which implements an MKLMemory class that exposes memory allocated via mkl_malloc and mkl_calloc to Python via the buffer protocol

The class uses an atomic counter incremented as __getbuffer__ and __releasebuffer__ are called to track the views on the buffer to permit use of mkl_realloc in the object (via realloc method). This concept was adapted from the PEP which revised the buffer protocol which proposed this kind of approach to tracking views on a buffer

Closes #18

@ndgrigorian
ndgrigorian force-pushed the feature/add-mkl-memory branch 5 times, most recently from aed1ff6 to a99e626 Compare April 12, 2026 07:19
@ndgrigorian
ndgrigorian marked this pull request as ready for review April 12, 2026 09:03
@ndgrigorian
ndgrigorian force-pushed the feature/add-mkl-memory branch 3 times, most recently from b2cc6fc to 00fea26 Compare May 10, 2026 02:02
Base automatically changed from use-meson-build to master July 21, 2026 14:49
Copilot AI lite review requested due to automatic review settings August 6, 2026 15:58
@ndgrigorian
ndgrigorian force-pushed the feature/add-mkl-memory branch from 00fea26 to c764a81 Compare August 6, 2026 15:58

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds a new MKLMemory Cython extension type backed by MKL’s allocator, exposes it from the top-level mkl package, and introduces tests/build changes to support C11 atomics and nogil MKL calls.

Changes:

  • Introduce mkl._mkl_memory with MKLMemory (allocation, buffer protocol, pickling, realloc).
  • Add pytest coverage for allocation, buffer protocol, and pickling behavior.
  • Update MKL C-API declarations/build to support nogil calls and C11 atomics (plus MSVC flag).

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
mkl/tests/test_mkl_memory.py Adds tests for MKLMemory creation, buffer protocol, and pickling behavior.
mkl/_py_mkl_service.pyx Releases the GIL around MKL buffer-free calls.
mkl/_mkl_service.pxd Marks MKL externs as nogil and adds malloc/calloc/realloc/free declarations.
mkl/_mkl_memory.pyx Adds the new MKLMemory Cython extension implementing allocation + buffer protocol + pickling.
mkl/init.py Exposes MKLMemory at the package top level.
meson.build Enables C11, adds MSVC atomics flag, and builds the new _mkl_memory extension.

Comment thread mkl/_mkl_memory.pyx Outdated
Comment thread mkl/_mkl_memory.pyx Outdated
Comment thread mkl/_mkl_memory.pyx
Comment thread mkl/_mkl_memory.pyx
Comment thread mkl/_mkl_memory.pyx
Comment thread mkl/_mkl_memory.pyx
Comment thread mkl/_mkl_memory.pyx Outdated
Comment thread mkl/_mkl_memory.pyx
Comment thread mkl/_mkl_memory.pyx
Comment thread mkl/_mkl_memory.pyx Outdated
@ndgrigorian
ndgrigorian force-pushed the feature/add-mkl-memory branch from 0d4ccfb to 0c75d30 Compare September 3, 2026 21:04
also address issues with undeclared variables and rename MKLMemory class members
@ndgrigorian
ndgrigorian force-pushed the feature/add-mkl-memory branch from 0c75d30 to 6aae4fb Compare September 3, 2026 21:34
@ndgrigorian

Copy link
Copy Markdown
Collaborator Author

@antonwolfy
Would be nice to get this reviewed and see if it can make it in the next release

@antonwolfy antonwolfy added this to the 2.9.0 release milestone Sep 4, 2026
@@ -0,0 +1,271 @@
# Copyright (c) 2018, Intel Corporation

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be a year when file is created

Suggested change
# Copyright (c) 2018, Intel Corporation
# Copyright (c) 2026, Intel Corporation

Comment thread meson.build
subdir: 'mkl'
)

py.extension_module(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please populate the changelog

Comment thread mkl/_mkl_memory.pyx
if new_nbytes <= 0:
raise ValueError("New number of bytes must be positive.")

with nogil:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There might be use-after-free issue:

  1. Thread B (holding GIL): passes exported_buffers == 0 and the refcount check.
  2. Thread B enters with nogil: → releases the GIL → calls mkl_realloc.
  3. Thread A acquires the GIL, runs memoryview(mem)__getbuffer__ reads the old _memory_ptr into buffer.buf, bumps the counter.
  4. Thread B's mkl_realloc frees/moves the old block, reacquires GIL, sets _memory_ptr = p.
  5. Thread A now holds a view into freed memory → UAF.

Comment thread mkl/_mkl_memory.pyx

if (p):
self._memory_ptr = p
self._nbytes = num * size

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs to validate there is no num > PY_SSIZE_T_MAX / size

Comment thread mkl/_mkl_memory.pyx
with nogil:
memcpy(self._memory_ptr, other_mem._memory_ptr, self._nbytes)

def __cinit__(self, *args, **kwargs):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No check on name of alignment keyword.
Any typo in name, like MKLMemory(1024, alignmnet=128) (instead of alignment) will be silently ignored and fallback on 64.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also no type-check before the Py_ssize_t conversion

Comment thread mkl/_mkl_memory.pyx
return self._nbytes

@property
def size(self):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That duplicates nbytes.
Also that collides with the constructor's .size parameter, which means something different.
And that collides with the NumPy convention where .size is the element count and .nbytes is the byte count.

Comment thread meson.build
cc = meson.get_compiler('c')
if cc.get_id() == 'msvc'
add_project_arguments(
'/experimental:c11atomics',

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/experimental:c11atomics requires VS 2022 17.5+ and fails hard on older toolchains.
Should we document the floor?

Comment thread mkl/_mkl_memory.pyx
def __repr__(self):
return (
f"<MKL memory allocation of {self._nbytes} bytes at "
f"{hex(<object>(<size_t>self._memory_ptr))}>"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be simplified:

Suggested change
f"{hex(<object>(<size_t>self._memory_ptr))}>"
f"{hex(self._pointer)}>"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both forms cythonized to the same:

with_cast — hex(<object>(<size_t>x)):

__pyx_t_1 = __Pyx_PyLong_FromSize_t(((size_t)__pyx_v_x)); ...
__pyx_t_2 = __Pyx_PyNumber_Hex(__pyx_t_1); ...

without_cast — hex(<size_t>x):

__pyx_t_1 = __Pyx_PyLong_FromSize_t(((size_t)__pyx_v_x)); ...
__pyx_t_2 = __Pyx_PyNumber_Hex(__pyx_t_1); ...

@@ -0,0 +1,271 @@
# Copyright (c) 2018, Intel Corporation

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we update AGENTS.md, .github/copilot-instructions.md and mkl/tests/AGENTS.md with the new test file?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The the same for _py_mkl_service files

Comment thread meson.build

cc = meson.get_compiler('c')
if cc.get_id() == 'msvc'
add_project_arguments(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is only needed for _py_mkl_service. We probably should not add it everywhere, considering it's experimental:

mkl_memory_c_args = c_args
if cc.get_id() == 'msvc'
    mkl_memory_c_args += '/experimental:c11atomics'
endif

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add memory classes that allocate memory using MKL allocator

3 participants