Coverage for cuda/core/_memory/_synchronous_memory_resource.pyx: 95.74%

47 statements  

« prev     ^ index     » next       coverage.py v7.16.0, created at 2026-09-10 02:27 +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._resource_handles 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 2? 1b2b3b4b5bX Y 6b7bZ 8b9b!b#bd $b%be 'b(b)b*b+b,b-b.b/b:b;b=b0 1 2 = f 3 4 5 F G a b 6 ] ^ _ ` { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b7 H I J K L M N O P Q R S T g h U i j k l m n o p q r s t u v w x y z A B V C D E W c

36  

37 self._device_id = Device(device_id).device_id 21b2b3b4b5bX Y 6b7bZ 8b9b!b#bd $b%be 'b(b)b*b+b,b-b.b/b:b;b=b0 1 2 = f 3 4 5 F G a b 6 ] ^ _ ` { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b7 H I J K L M N O P Q R S T g h U i j k l m n o p q r s t u v w x y z A B V C D E W c

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 21b2b3b4b5bX Y 6b7bZ 8b9b!b#bd $b%be 'b(b)b*b+b,b-b.b/b:b;b=b0 1 2 = f 3 4 5 F G a b 6 ] ^ _ ` { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b7 H I J K L M N O P Q R S T g h U i j k l m n o p q r s t u v w x y z A B V C D E W c

42  

43 def _resolve_context(self) -> Context: 

44 cdef ContextHandle h_context 

45 if self._context is None: 21b2b3b4b5bX Y @ 6b[ 7bZ 8b9b!b#bd $b%be 'b(b)b*b+b,b-b.b/b:b;b=b0 1 2 = f 3 4 5 F G a b 6 ] ^ _ ` { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b7 H I J K L M N O P Q R S T g h U i j k 8 l 9 ! # m n o p $ q r % ' s t u v ( ) w * + x , y z A B / V : - C ; . D E W c

46 h_context = get_primary_context(self._device_id) 1ab

47 if not h_context: 1ab

48 HANDLE_RETURN(get_last_error()) 

49 self._context = Context._from_handle( 1ab

50 Context, h_context, self._device_id) 1ab

51 return self._context 21b2b3b4b5bX Y @ 6b[ 7bZ 8b9b!b#bd $b%be 'b(b)b*b+b,b-b.b/b:b;b=b0 1 2 = f 3 4 5 F G a b 6 ] ^ _ ` { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b7 H I J K L M N O P Q R S T g h U i j k 8 l 9 ! # m n o p $ q r % ' s t u v ( ) w * + x , y z A B / V : - C ; . D E W c

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() 21b2b3b4b5bX Y @ 6b[ 7bZ 8b9b!b#bd $b%be 'b(b)b*b+b,b-b.b/b:b;b=b0 1 2 = f 3 4 5 F G a b 6 ] ^ _ ` { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b7 H I J K L M N O P Q R S T g h U i j k 8 l 9 ! # m n o p $ q r % ' s t u v ( ) w * + x , y z A B / V : - C ; . D E W c

63 cdef Stream dealloc_stream = None 21b2b3b4b5bX Y @ 6b[ 7bZ 8b9b!b#bd $b%be 'b(b)b*b+b,b-b.b/b:b;b=b0 1 2 = f 3 4 5 F G a b 6 ] ^ _ ` { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b7 H I J K L M N O P Q R S T g h U i j k 8 l 9 ! # m n o p $ q r % ' s t u v ( ) w * + x , y z A B / V : - C ; . D E W c

64 if stream is not None: 21b2b3b4b5bX Y @ 6b[ 7bZ 8b9b!b#bd $b%be 'b(b)b*b+b,b-b.b/b:b;b=b0 1 2 = f 3 4 5 F G a b 6 ] ^ _ ` { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b7 H I J K L M N O P Q R S T g h U i j k 8 l 9 ! # m n o p $ q r % ' s t u v ( ) w * + x , y z A B / V : - C ; . D E W c

65 dealloc_stream = Stream_accept(stream) 21b2b3b4b5bX Y @ 6b[ 7bZ 8b9b!b#bd $b%be 'b(b)b*b+b,b-b.b/b:b;b=b0 1 2 = f 3 4 5 F G a 6 ] ^ _ ` { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b7 H I J K L M N O P Q R S T g h U i j k 8 l 9 ! # m n o p $ q r % ' s t u v ( ) w * + x , y z A B / V : - C ; . D E W c

66 if dealloc_stream is None or Stream_is_default_token(dealloc_stream): 21b2b3b4b5bX Y @ 6b[ 7bZ 8b9b!b#bd $b%be 'b(b)b*b+b,b-b.b/b:b;b=b0 1 2 = f 3 4 5 F G a b 6 ] ^ _ ` { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b7 H I J K L M N O P Q R S T g h U i j k 8 l 9 ! # m n o p $ q r % ' s t u v ( ) w * + x , y z A B / V : - C ; . D E W c

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( 2d e = f F G a b ] ^ _ ` { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0bH I J K L M N O P Q R S T g h U i j k 8 l 9 ! # m n o p $ q r % ' s t u v ( ) w * + x , y z A B / V : - C ; . D E W c

75 Stream, create_context_bound_legacy_stream(context._h_context)) 2d e = f F G a b ] ^ _ ` { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0bH I J K L M N O P Q R S T g h U i j k 8 l 9 ! # m n o p $ q r % ' s t u v ( ) w * + x , y z A B / V : - C ; . D E W c

76  

77 cdef cydriver.CUdeviceptr ptr = 0 21b2b3b4b5bX Y @ 6b[ 7bZ 8b9b!b#bd $b%be 'b(b)b*b+b,b-b.b/b:b;b=b0 1 2 = f 3 4 5 F G a b 6 ] ^ _ ` { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b7 H I J K L M N O P Q R S T g h U i j k 8 l 9 ! # m n o p $ q r % ' s t u v ( ) w * + x , y z A B / V : - C ; . D E W c

78 if size: 2? 1b2b3b4b5bX Y @ 6b[ 7bZ 8b9b!b#bd $b%be 'b(b)b*b+b,b-b.b/b:b;b=b0 1 2 = f 3 4 5 F G a b 6 ] ^ _ ` { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b7 H I J K L M N O P Q R S T g h U i j k 8 l 9 ! # m n o p $ q r % ' s t u v ( ) w * + x , y z A B / V : - C ; . D E W c

79 with nogil: 21b2b3b4b5bX Y @ 6b[ 7bZ 8b9b!b#bd $b%be 'b(b)b*b+b,b-b.b/b:b;b=b0 1 2 f 3 4 5 F G a b 6 ] ^ _ ` { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b7 H I J K L M N O P Q R S T g h U i j k 8 l 9 ! # m n o p $ q r % ' s t u v ( ) w * + x , y z A B / V : - C ; . D E W c

80 HANDLE_RETURN(deviceptr_alloc_raw(&ptr, size, context._h_context)) 21b2b3b4b5bX Y @ 6b[ 7bZ 8b9b!b#bd $b%be 'b(b)b*b+b,b-b.b/b:b;b=b0 1 2 f 3 4 5 F G a b 6 ] ^ _ ` { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b7 H I J K L M N O P Q R S T g h U i j k 8 l 9 ! # m n o p $ q r % ' s t u v ( ) w * + x , y z A B / V : - C ; . D E W c

81 return Buffer._init(<uintptr_t>ptr, size, self, stream=dealloc_stream) 21b2b3b4b5bX Y @ 6b[ 7bZ 8b9b!b#bd $b%be 'b(b)b*b+b,b-b.b/b:b;b=b0 1 2 = f 3 4 5 F G a b 6 ] ^ _ ` { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b7 H I J K L M N O P Q R S T g h U i j k 8 l 9 ! # m n o p $ q r % ' s t u v ( ) w * + x , y z A B / V : - C ; . D E W c

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?b@b[bX Y @ ]b[ ^bZ _b`b{b|bd }b~be acbcccdcecfcgchcicjckclc0 1 2 = f 3 4 5 F G a b 6 mcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'c(c)c*c+c,c-c7 H I J K L M N O P Q R S T g h U i j k 8 l 9 ! # m n o p $ q r % ' s t u v ( ) w * + x , y z A B / V : - C ; . D E W c

91 Stream_accept(stream).sync() 2?b@b[bX Y @ ]b[ ^bZ _b`b{b|bd }b~be acbcccdcecfcgchcicjckclc0 1 2 = f 3 4 5 F G a b 6 mcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'c(c)c*c+c,c-c7 H I J K L M N O P Q R S T g h U i j k 8 l 9 ! # m n o p $ q r % ' s t u v ( ) w * + x , y z A B / V : - C ; . D E W c

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?b@b[bX Y @ ]b[ ^bZ _b`b{b|bd }b~be acbcccdcecfcgchcicjckclc0 1 2 = f 3 4 5 F G a b 6 mcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'c(c)c*c+c,c-c7 H I J K L M N O P Q R S T g h U i j k 8 l 9 ! # m n o p $ q r % ' s t u v ( ) w * + x , y z A B / V : - C ; . D E W c

101 devptr = <cydriver.CUdeviceptr><uintptr_t>int(ptr) 2?b@b[bX Y @ ]b[ ^bZ _b`b{b|bd }b~be acbcccdcecfcgchcicjckclc0 1 2 f 3 4 5 F G a b 6 mcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'c(c)c*c+c,c-c7 H I J K L M N O P Q R S T g h U i j k 8 l 9 ! # m n o p $ q r % ' s t u v ( ) w * + x , y z A B / V : - C ; . D E W c

102 with nogil: 2?b@b[bX Y @ ]b[ ^bZ _b`b{b|bd }b~be acbcccdcecfcgchcicjckclc0 1 2 f 3 4 5 F G a b 6 mcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'c(c)c*c+c,c-c7 H I J K L M N O P Q R S T g h U i j k 8 l 9 ! # m n o p $ q r % ' s t u v ( ) w * + x , y z A B / V : - C ; . D E W c

103 HANDLE_RETURN(cydriver.cuMemFree(devptr)) 2?b@b[bX Y @ ]b[ ^bZ _b`b{b|bd }b~be acbcccdcecfcgchcicjckclc0 1 2 f 3 4 5 F G a b 6 mcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'c(c)c*c+c,c-c7 H I J K L M N O P Q R S T g h U i j k 8 l 9 ! # m n o p $ q r % ' s t u v ( ) w * + x , y z A B / V : - C ; . D E W c

104  

105 @property 

106 def is_device_accessible(self) -> bool: 

107 return True 21b2b3b4b5bX Y @ 6b[ 7bZ 8b9b!b#bd $b%be 'b(b)b*b+b,b-b.b/b:b;b=b0 1 2 = f 3 4 5 F G a b 6 ] ^ _ ` { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b7 H I J K L M N O P Q R S T g h U i j k 8 l 9 ! # m n o p $ q r % ' s t u v ( ) w * + x , y z A B / V : - C ; . D E W c

108  

109 @property 

110 def is_host_accessible(self) -> bool: 

111 return False 1ac

112  

113 @property 

114 def device_id(self) -> int: 

115 return self._device_id 2? .c/cX Y :cd ;ce =c?c@c[c= f a g h i j k 8 l 9 ! # m n o p $ q r % ' s t u v ( ) w * + x , y z A B - C . D E c