Coverage for cuda/core/_memory/_synchronous_memory_resource.pyx: 95.74%
47 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-16 01:23 +0000
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-16 01:23 +0000
1# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2#
3# SPDX-License-Identifier: Apache-2.0
5from __future__ import annotations
7from libc.stdint cimport uintptr_t
9from cuda.bindings cimport cydriver
10from cuda.core._context cimport Context
11from cuda.core._memory._buffer cimport Buffer, MemoryResource
12from cuda.core._rt cimport (
13 ContextHandle,
14 create_context_bound_legacy_stream,
15 deviceptr_alloc_raw,
16 get_last_error,
17 get_primary_context,
18)
19from cuda.core._stream cimport Stream, Stream_accept, Stream_is_default_token
20from cuda.core._utils.cuda_utils cimport HANDLE_RETURN
22from typing import TYPE_CHECKING
24if TYPE_CHECKING:
25 from cuda.core.graph import GraphBuilder
26 from cuda.core.typing import DevicePointerType
28__all__ = []
31class _SynchronousMemoryResource(MemoryResource):
32 __slots__ = ("_context", "_device_id")
34 def __init__(self, device_id: int, context=None) -> None:
35 from .._device import Device 2fb; xbybc = ? @ zbAbBb/ : CbDb[ EbFbGbHbh IbJbi KbLbMbNbObPbQbRbSbTbUbVb] ^ _ ebj gb` { | } ~ abbbZ 0 a b cbjbkblbmbnbobpbqbrbsbtbubvbwbd e f 1 2 db3 4 5 6 7 8 9 ! # $ % ' ( k l ) m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R * + , S T - U V W . X Y g
37 self._device_id = Device(device_id).device_id 2; xbybc = ? @ zbAbBb/ : CbDb[ EbFbGbHbh IbJbi KbLbMbNbObPbQbRbSbTbUbVb] ^ _ ebj gb` { | } ~ abbbZ 0 a b cbjbkblbmbnbobpbqbrbsbtbubvbwbd e f 1 2 db3 4 5 6 7 8 9 ! # $ % ' ( k l ) m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R * + , S T - U V W . X Y g
38 # Resolved lazily (in _resolve_context) so that construction with
39 # context=None does no CUDA work; the primary context is retained
40 # only once actually needed, on the first allocate()/deallocate().
41 self._context = context 2; xbybc = ? @ zbAbBb/ : CbDb[ EbFbGbHbh IbJbi KbLbMbNbObPbQbRbSbTbUbVb] ^ _ ebj gb` { | } ~ abbbZ 0 a b cbjbkblbmbnbobpbqbrbsbtbubvbwbd e f 1 2 db3 4 5 6 7 8 9 ! # $ % ' ( k l ) m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R * + , S T - U V W . X Y g
43 def _resolve_context(self) -> Context:
44 cdef ContextHandle h_context
45 if self._context is None: 2; xbybc = ? @ zbAbBb/ : hbCbibDb[ EbFbGbHbh IbJbi KbLbMbNbObPbQbRbSbTbUbVb] ^ _ ebj gb` { | } ~ abbbZ 0 a b cbjbkblbmbnbobpbqbrbsbtbubvbwbd e f 1 2 db3 4 5 6 7 8 9 ! # $ % ' ( k l ) m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R * + , S T - U V W . X Y g
46 h_context = get_primary_context(self._device_id) 2c gba b
47 if not h_context: 2c gba b
48 HANDLE_RETURN(get_last_error())
49 self._context = Context._from_handle( 2c gba b
50 Context, h_context, self._device_id) 2c gba b
51 return self._context 2; xbybc = ? @ zbAbBb/ : hbCbibDb[ EbFbGbHbh IbJbi KbLbMbNbObPbQbRbSbTbUbVb] ^ _ ebj gb` { | } ~ abbbZ 0 a b cbjbkblbmbnbobpbqbrbsbtbubvbwbd e f 1 2 db3 4 5 6 7 8 9 ! # $ % ' ( k l ) m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R * + , S T - U V W . X Y g
53 def allocate(
54 self,
55 size_t size,
56 *,
57 stream: Stream | GraphBuilder | None = None,
58 ) -> Buffer:
59 # cuMemAlloc/cuMemFree are synchronous; a caller-supplied stream is
60 # accepted (and validated) for interface conformance and, if it is a
61 # real stream, recorded as the stream that orders deallocation.
62 cdef Context context = self._resolve_context() 2; xbybc = ? @ zbAbBb/ : hbCbibDb[ EbFbGbHbh IbJbi KbLbMbNbObPbQbRbSbTbUbVb] ^ _ ebj gb` { | } ~ abbbZ 0 a b cbjbkblbmbnbobpbqbrbsbtbubvbwbd e f 1 2 db3 4 5 6 7 8 9 ! # $ % ' ( k l ) m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R * + , S T - U V W . X Y g
63 cdef Stream dealloc_stream = None 2; xbybc = ? @ zbAbBb/ : hbCbibDb[ EbFbGbHbh IbJbi KbLbMbNbObPbQbRbSbTbUbVb] ^ _ ebj gb` { | } ~ abbbZ 0 a b cbjbkblbmbnbobpbqbrbsbtbubvbwbd e f 1 2 db3 4 5 6 7 8 9 ! # $ % ' ( k l ) m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R * + , S T - U V W . X Y g
64 if stream is not None: 2; xbybc = ? @ zbAbBb/ : hbCbibDb[ EbFbGbHbh IbJbi KbLbMbNbObPbQbRbSbTbUbVb] ^ _ ebj gb` { | } ~ abbbZ 0 a b cbjbkblbmbnbobpbqbrbsbtbubvbwbd e f 1 2 db3 4 5 6 7 8 9 ! # $ % ' ( k l ) m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R * + , S T - U V W . X Y g
65 dealloc_stream = Stream_accept(stream) 2; xbybc = ? @ zbAbBb/ : hbCbibDb[ EbFbGbHbh IbJbi KbLbMbNbObPbQbRbSbTbUbVb] ^ _ ebj ` { | } ~ abbbZ 0 a cbjbkblbmbnbobpbqbrbsbtbubvbwbd e f 1 2 db3 4 5 6 7 8 9 ! # $ % ' ( k l ) m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R * + , S T - U V W . X Y g
66 if dealloc_stream is None or Stream_is_default_token(dealloc_stream): 2; xbybc = ? @ zbAbBb/ : hbCbibDb[ EbFbGbHbh IbJbi KbLbMbNbObPbQbRbSbTbUbVb] ^ _ ebj gb` { | } ~ abbbZ 0 a b cbjbkblbmbnbobpbqbrbsbtbubvbwbd e f 1 2 db3 4 5 6 7 8 9 ! # $ % ' ( k l ) m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R * + , S T - U V W . X Y g
67 # A default-stream token carries no context of its own; Buffer._init
68 # would bind it to whichever context is current when it records the
69 # deallocation stream (and fail if none is). Bind it to this
70 # resource's context instead, so Buffer teardown frees in the right
71 # context no matter what is current then. Always the legacy token:
72 # a per-thread token would also arm the cross-thread PTDS warning,
73 # which is noise for a synchronous resource.
74 dealloc_stream = Stream._from_handle( 2h i ebj gbZ 0 a b jbkblbmbnbobpbqbrbsbtbubvbwbd e f 1 2 3 4 5 6 7 8 9 ! # $ % ' ( k l ) m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R * + , S T - U V W . X Y g
75 Stream, create_context_bound_legacy_stream(context._h_context)) 2h i ebj gbZ 0 a b jbkblbmbnbobpbqbrbsbtbubvbwbd e f 1 2 3 4 5 6 7 8 9 ! # $ % ' ( k l ) m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R * + , S T - U V W . X Y g
77 cdef cydriver.CUdeviceptr ptr = 0 2; xbybc = ? @ zbAbBb/ : hbCbibDb[ EbFbGbHbh IbJbi KbLbMbNbObPbQbRbSbTbUbVb] ^ _ ebj gb` { | } ~ abbbZ 0 a b cbjbkblbmbnbobpbqbrbsbtbubvbwbd e f 1 2 db3 4 5 6 7 8 9 ! # $ % ' ( k l ) m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R * + , S T - U V W . X Y g
78 if size: 2fb; xbybc = ? @ zbAbBb/ : hbCbibDb[ EbFbGbHbh IbJbi KbLbMbNbObPbQbRbSbTbUbVb] ^ _ ebj gb` { | } ~ abbbZ 0 a b cbjbkblbmbnbobpbqbrbsbtbubvbwbd e f 1 2 db3 4 5 6 7 8 9 ! # $ % ' ( k l ) m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R * + , S T - U V W . X Y g
79 with nogil: 2; xbybc = ? @ zbAbBb/ : hbCbibDb[ EbFbGbHbh IbJbi KbLbMbNbObPbQbRbSbTbUbVb] ^ _ j gb` { | } ~ abbbZ 0 a b cbjbkblbmbnbobpbqbrbsbtbubvbwbd e f 1 2 db3 4 5 6 7 8 9 ! # $ % ' ( k l ) m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R * + , S T - U V W . X Y g
80 HANDLE_RETURN(deviceptr_alloc_raw(&ptr, size, context._h_context)) 2; xbybc = ? @ zbAbBb/ : hbCbibDb[ EbFbGbHbh IbJbi KbLbMbNbObPbQbRbSbTbUbVb] ^ _ j gb` { | } ~ abbbZ 0 a b cbjbkblbmbnbobpbqbrbsbtbubvbwbd e f 1 2 db3 4 5 6 7 8 9 ! # $ % ' ( k l ) m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R * + , S T - U V W . X Y g
81 return Buffer._init(<uintptr_t>ptr, size, self, stream=dealloc_stream) 2; xbybc = ? @ zbAbBb/ : hbCbibDb[ EbFbGbHbh IbJbi KbLbMbNbObPbQbRbSbTbUbVb] ^ _ ebj ` { | } ~ abbbZ 0 a b cbjbkblbmbnbobpbqbrbsbtbubvbwbd e f 1 2 db3 4 5 6 7 8 9 ! # $ % ' ( k l ) m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R * + , S T - U V W . X Y g
83 def deallocate(
84 self,
85 ptr: DevicePointerType,
86 size_t size,
87 *,
88 stream: Stream | GraphBuilder | None = None,
89 ) -> None:
90 if stream is not None: 2; c = ? @ WbXbYb/ : hbZbib0b[ 1b2b3b4bh 5b6bi 7b8b9b!b#b$b%b'b(b)b*b+b] ^ _ ebj ` { | } ~ abbbZ 0 a b cb,b-b.b/b:b;b=b?b@b[b]b^b_bd e f 1 2 db3 4 5 6 7 8 9 ! # $ % ' ( k l ) m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R * + , S T - U V W . X Y g
91 Stream_accept(stream).sync() 2; c = ? @ WbXbYb/ : hbZbib0b[ 1b2b3b4bh 5b6bi 7b8b9b!b#b$b%b'b(b)b*b+b] ^ _ ebj ` { | } ~ abbbZ 0 a b cb,b-b.b/b:b;b=b?b@b[b]b^b_bd e f 1 2 db3 4 5 6 7 8 9 ! # $ % ' ( k l ) m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R * + , S T - U V W . X Y g
92 # No context switch here, by design (settled in the review of #2750):
93 # cuMemFree does not need a current context. The driver resolves the
94 # allocation's owning context from the pointer through unified
95 # addressing and frees it there (cuapiMemFree_common: "a current
96 # context is not required to free the device memory"). On the Buffer
97 # teardown path the C++ deleter has additionally already made the
98 # recorded deallocation context, bound by allocate() above, current.
99 cdef cydriver.CUdeviceptr devptr
100 if size: 2; c = ? @ WbXbYb/ : hbZbib0b[ 1b2b3b4bh 5b6bi 7b8b9b!b#b$b%b'b(b)b*b+b] ^ _ ebj ` { | } ~ abbbZ 0 a b cb,b-b.b/b:b;b=b?b@b[b]b^b_bd e f 1 2 db3 4 5 6 7 8 9 ! # $ % ' ( k l ) m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R * + , S T - U V W . X Y g
101 devptr = <cydriver.CUdeviceptr><uintptr_t>int(ptr) 2; c = ? @ WbXbYb/ : hbZbib0b[ 1b2b3b4bh 5b6bi 7b8b9b!b#b$b%b'b(b)b*b+b] ^ _ j ` { | } ~ abbbZ 0 a b cb,b-b.b/b:b;b=b?b@b[b]b^b_bd e f 1 2 db3 4 5 6 7 8 9 ! # $ % ' ( k l ) m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R * + , S T - U V W . X Y g
102 with nogil: 2; c = ? @ WbXbYb/ : hbZbib0b[ 1b2b3b4bh 5b6bi 7b8b9b!b#b$b%b'b(b)b*b+b] ^ _ j ` { | } ~ abbbZ 0 a b cb,b-b.b/b:b;b=b?b@b[b]b^b_bd e f 1 2 db3 4 5 6 7 8 9 ! # $ % ' ( k l ) m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R * + , S T - U V W . X Y g
103 HANDLE_RETURN(cydriver.cuMemFree(devptr)) 2; c = ? @ WbXbYb/ : hbZbib0b[ 1b2b3b4bh 5b6bi 7b8b9b!b#b$b%b'b(b)b*b+b] ^ _ j ` { | } ~ abbbZ 0 a b cb,b-b.b/b:b;b=b?b@b[b]b^b_bd e f 1 2 db3 4 5 6 7 8 9 ! # $ % ' ( k l ) m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R * + , S T - U V W . X Y g
105 @property
106 def is_device_accessible(self) -> bool:
107 return True 2; xbybc = ? @ zbAbBb/ : hbCbibDb[ EbFbGbHbh IbJbi KbLbMbNbObPbQbRbSbTbUbVb] ^ _ ebj ` { | } ~ abbbZ 0 a b cbjbkblbmbnbobpbqbrbsbtbubvbwbd e f 1 2 db3 4 5 6 7 8 9 ! # $ % ' ( k l ) m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R * + , S T - U V W . X Y g
109 @property
110 def is_host_accessible(self) -> bool:
111 return False 1adefg
113 @property
114 def device_id(self) -> int:
115 return self._device_id 2fb`b{b/ : |bh }bi ~bacbcccebj a d e f k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y g