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

1# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 

2# 

3# SPDX-License-Identifier: Apache-2.0 

4  

5from __future__ import annotations 

6  

7from libc.stdint cimport uintptr_t 

8  

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 

21  

22from typing import TYPE_CHECKING 

23  

24if TYPE_CHECKING: 

25 from cuda.core.graph import GraphBuilder 

26 from cuda.core.typing import DevicePointerType 

27  

28__all__ = [] 

29  

30  

31class _SynchronousMemoryResource(MemoryResource): 

32 __slots__ = ("_context", "_device_id") 

33  

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

36  

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

42  

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

52  

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

76  

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

82  

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

104  

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

108  

109 @property 

110 def is_host_accessible(self) -> bool: 

111 return False 1adefg

112  

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