已合并
[fix][2.7.1]add getMemoryFraction attribute for torch._C #31101
wuyouqi1创建于 2月27日
[fix][2.7.1]add getMemoryFraction attribute for torch._C #31101
已合并
wuyouqi1创建于 2月27日
已删除 :v2.7.1合入到Ascend/pytorchv2.7.1
11 个文件变更+102-1
@@ -192,6 +192,24 @@ class TestNpu(TestCase):
192 torch_npu.npu.empty_cache()192 torch_npu.npu.empty_cache()
193 torch_npu.npu.reset_peak_memory_stats()193 torch_npu.npu.reset_peak_memory_stats()
194 194 
195+ def test_get_per_process_memory_fraction(self):
196+ # get the initial memory fraction
197+ init_fraction = torch_npu.npu.get_per_process_memory_fraction()
198+ 
199+ # set and get the limiting cases
200+ torch_npu.npu.set_per_process_memory_fraction(1.0)
201+ self.assertEqual(torch_npu.npu.get_per_process_memory_fraction(), 1.0)
202+ torch_npu.npu.set_per_process_memory_fraction(0.0)
203+ self.assertEqual(torch_npu.npu.get_per_process_memory_fraction(), 0.0)
204+ 
205+ # test a few random cases
206+ for val in torch.rand(3):
207+ torch_npu.npu.set_per_process_memory_fraction(float(val))
208+ self.assertEqual(torch_npu.npu.get_per_process_memory_fraction(), float(val))
209+ 
210+ # restore the initial memory fraction
211+ torch_npu.npu.set_per_process_memory_fraction(init_fraction)
212+ 
195 def test_set_per_process_memory_fraction(self):213 def test_set_per_process_memory_fraction(self):
196 # test invalid fraction value.214 # test invalid fraction value.
197 with self.assertRaisesRegex(TypeError, "Invalid type"):215 with self.assertRaisesRegex(TypeError, "Invalid type"):
@@ -1115,6 +1115,9 @@
1115 "torch_npu.npu.set_option": {1115 "torch_npu.npu.set_option": {
1116 "signature": "(option)"1116 "signature": "(option)"
1117 },1117 },
1118+ "torch_npu.npu.get_per_process_memory_fraction": {
1119+ "signature": "(device=None) -> float"
1120+ },
1118 "torch_npu.npu.set_per_process_memory_fraction": {1121 "torch_npu.npu.set_per_process_memory_fraction": {
1119 "signature": "(fraction, device=None) -> None"1122 "signature": "(fraction, device=None) -> None"
1120 },1123 },
@@ -1328,6 +1331,9 @@
1328 "torch_npu.npu.memory.reset_peak_memory_stats": {1331 "torch_npu.npu.memory.reset_peak_memory_stats": {
1329 "signature": "(device=None)"1332 "signature": "(device=None)"
1330 },1333 },
1334+ "torch_npu.npu.memory.get_per_process_memory_fraction": {
1335+ "signature": "(device=None) -> float"
1336+ },
1331 "torch_npu.npu.memory.set_per_process_memory_fraction": {1337 "torch_npu.npu.memory.set_per_process_memory_fraction": {
1332 "signature": "(fraction, device=None) -> None"1338 "signature": "(fraction, device=None) -> None"
1333 },1339 },
@@ -31649,5 +31649,6 @@
31649 "test_use_pinned_memory_for_d2h (__main__.TestSerialization)": ["", [""]],31649 "test_use_pinned_memory_for_d2h (__main__.TestSerialization)": ["", [""]],
31650 "test_fake_autocast_fft_fftshift_npu_float32 (__main__.TestFakeTensorPRIVATEUSE1)": ["", [""]],31650 "test_fake_autocast_fft_fftshift_npu_float32 (__main__.TestFakeTensorPRIVATEUSE1)": ["", [""]],
31651 "test_fake_autocast_fft_ifftshift_npu_float32 (__main__.TestFakeTensorPRIVATEUSE1)": ["", [""]],31651 "test_fake_autocast_fft_ifftshift_npu_float32 (__main__.TestFakeTensorPRIVATEUSE1)": ["", [""]],
31652- "test_index_put_accumulate_large_tensor_npu (__main__.TestIndexingPRIVATEUSE1)": ["", ["910A"]]31652+ "test_index_put_accumulate_large_tensor_npu (__main__.TestIndexingPRIVATEUSE1)": ["", ["910A"]],
31653+ "test_serialization_array_with_empty (__main__.TestNpu)": ["", [""]]
31653}31654}
@@ -1575,6 +1575,20 @@ public:
1575 }1575 }
1576 }1576 }
1577 1577 
1578+ /** get memory fraction limiting maximum allocated memory **/
1579+ double getMemoryFraction()
1580+ {
1581+ if (!set_fraction) {
1582+ return 1.0;
1583+ }
1584+ 
1585+ size_t device_free = 0;
1586+ size_t device_total = 0;
1587+ NPU_CHECK_ERROR(aclrtGetMemInfo(ACL_HBM_MEM, &device_free, &device_total));
1588+ return static_cast<double>(allowed_memory_maximum) /
1589+ static_cast<double>(device_total);
1590+ }
1591+ 
1578 /* * set memory fraction to limit maximum allocated memory * */1592 /* * set memory fraction to limit maximum allocated memory * */
1579 void setMemoryFraction(double fraction)1593 void setMemoryFraction(double fraction)
1580 {1594 {
@@ -3155,6 +3169,15 @@ public:
3155 device_allocator[block->device]->free(block);3169 device_allocator[block->device]->free(block);
3156 }3170 }
3157 3171 
3172+ double getMemoryFraction(int device) override
3173+ {
3174+ TORCH_INTERNAL_ASSERT(
3175+ 0 <= device && device < device_allocator.size(), "Allocator not initialized for device ",
3176+ device, ": did you call init?", PTA_ERROR(ErrCode::PARAM));
3177+ NPU_CHECK_ERROR(c10_npu::SetDevice(device));
3178+ return device_allocator[device]->getMemoryFraction();
3179+ }
3180+ 
3158 void setMemoryFraction(double fraction, int device) override3181 void setMemoryFraction(double fraction, int device) override
3159 {3182 {
3160 TORCH_INTERNAL_ASSERT(0 <= device && device < device_allocator.size(), "Allocator not initialized for device ",3183 TORCH_INTERNAL_ASSERT(0 <= device && device < device_allocator.size(), "Allocator not initialized for device ",
@@ -201,6 +201,7 @@ public:
201 virtual void raw_delete(void* ptr) = 0;201 virtual void raw_delete(void* ptr) = 0;
202 virtual void init(int device_count) = 0;202 virtual void init(int device_count) = 0;
203 virtual bool initialized() = 0;203 virtual bool initialized() = 0;
204+ virtual double getMemoryFraction(int device) = 0;
204 virtual void setMemoryFraction(double fraction, int device) = 0;205 virtual void setMemoryFraction(double fraction, int device) = 0;
205 virtual void emptyCacheImpl(bool check_error, bool free_physical) = 0;206 virtual void emptyCacheImpl(bool check_error, bool free_physical) = 0;
206 virtual void emptyCache(bool check_error) = 0;207 virtual void emptyCache(bool check_error) = 0;
@@ -305,6 +306,11 @@ inline void init()
305 return get()->init(device_count);306 return get()->init(device_count);
306}307}
307 308 
309+inline double getMemoryFraction(int device)
310+{
311+ return get()->getMemoryFraction(device);
312+}
313+ 
308inline void setMemoryFraction(double fraction, int device)314inline void setMemoryFraction(double fraction, int device)
309{315{
310 return get()->setMemoryFraction(fraction, device);316 return get()->setMemoryFraction(fraction, device);
@@ -1104,6 +1104,24 @@ PyObject *THNPModule_is_jit_compile_false_wrap(PyObject *self, PyObject *noargs)
1104 END_HANDLE_TH_ERRORS1104 END_HANDLE_TH_ERRORS
1105}1105}
1106 1106 
1107+PyObject* THNPModule_getMemoryFraction(PyObject* _unused, PyObject* args)
1108+{
1109+ HANDLE_TH_ERRORS
1110+ PyObject* device_o = nullptr;
1111+ if (!PyArg_ParseTuple(args, "O", &device_o)) {
1112+ THPUtils_invalidArguments(
1113+ args,
1114+ nullptr,
1115+ "get_memory_fraction",
1116+ 1,
1117+ "(int device);");
1118+ return nullptr;
1119+ }
1120+ int64_t device_index = PyLong_AsLongLong(device_o);
1121+ return PyFloat_FromDouble(c10_npu::NPUCachingAllocator::getMemoryFraction(device_index));
1122+ END_HANDLE_TH_ERRORS
1123+}
1124+ 
1107PyObject* THNPModule_setMemoryFraction(PyObject *_unused, PyObject *args)1125PyObject* THNPModule_setMemoryFraction(PyObject *_unused, PyObject *args)
1108{1126{
1109 HANDLE_TH_ERRORS1127 HANDLE_TH_ERRORS
@@ -2268,6 +2286,7 @@ static struct PyMethodDef THNPModule_methods[] = {
2268 {"_npu_eraseStream", (PyCFunction)THNPModule_npu_eraseStream_wrap, METH_VARARGS | METH_KEYWORDS, nullptr},2286 {"_npu_eraseStream", (PyCFunction)THNPModule_npu_eraseStream_wrap, METH_VARARGS | METH_KEYWORDS, nullptr},
2269 {"_npu_isCurrentStreamCapturing", (PyCFunction)THNPModule_isCurrentStreamCapturing_wrap, METH_NOARGS, nullptr},2287 {"_npu_isCurrentStreamCapturing", (PyCFunction)THNPModule_isCurrentStreamCapturing_wrap, METH_NOARGS, nullptr},
2270 {"_npu_is_jit_compile_false", (PyCFunction)THNPModule_is_jit_compile_false_wrap, METH_NOARGS, nullptr},2288 {"_npu_is_jit_compile_false", (PyCFunction)THNPModule_is_jit_compile_false_wrap, METH_NOARGS, nullptr},
2289+ {"_npu_getMemoryFraction", (PyCFunction) THNPModule_getMemoryFraction, METH_VARARGS, nullptr},
2271 {"_npu_setMemoryFraction", (PyCFunction) THNPModule_setMemoryFraction, METH_VARARGS, nullptr},2290 {"_npu_setMemoryFraction", (PyCFunction) THNPModule_setMemoryFraction, METH_VARARGS, nullptr},
2272 {"_npu_emptyCache", (PyCFunction) THNPModule_emptyCache, METH_NOARGS, nullptr},2291 {"_npu_emptyCache", (PyCFunction) THNPModule_emptyCache, METH_NOARGS, nullptr},
2273 {"_npu_hostEmptyCache", (PyCFunction) THNPModule_npu_hostEmptyCache, METH_NOARGS, nullptr},2292 {"_npu_hostEmptyCache", (PyCFunction) THNPModule_npu_hostEmptyCache, METH_NOARGS, nullptr},
@@ -175,6 +175,14 @@ bool NPUPluggableAllocator::initialized()
175 return initialized_;175 return initialized_;
176}176}
177 177 
178+double NPUPluggableAllocator::getMemoryFraction(int device)
179+{
180+ TORCH_CHECK(
181+ false,
182+ "NPUPluggableAllocator does not yet support getMemoryFraction. "
183+ "If you need it, please file an issue describing your use case.");
184+}
185+ 
178void NPUPluggableAllocator::setMemoryFraction(double fraction, int device)186void NPUPluggableAllocator::setMemoryFraction(double fraction, int device)
179{187{
180 if (memory_fraction_fn_) {188 if (memory_fraction_fn_) {
@@ -58,6 +58,7 @@ struct NPUPluggableAllocator
58 void raw_delete(void* ptr) override;58 void raw_delete(void* ptr) override;
59 void init(int device_count) override;59 void init(int device_count) override;
60 bool initialized() override;60 bool initialized() override;
61+ double getMemoryFraction(int device) override;
61 void setMemoryFraction(double fraction, int device) override;62 void setMemoryFraction(double fraction, int device) override;
62 void emptyCacheImpl(bool check_error, bool free_physical) override;63 void emptyCacheImpl(bool check_error, bool free_physical) override;
63 void emptyCache(bool check_error) override;64 void emptyCache(bool check_error) override;
@@ -32,6 +32,7 @@ torch_non_c_binding_in_graph_functions_npu = dict.fromkeys(
32 "torch.npu.memory.reset_max_memory_cached",32 "torch.npu.memory.reset_max_memory_cached",
33 "torch.npu.memory.reset_peak_host_memory_stats",33 "torch.npu.memory.reset_peak_host_memory_stats",
34 "torch.npu.memory.reset_peak_memory_stats",34 "torch.npu.memory.reset_peak_memory_stats",
35+ "torch.npu.memory.get_per_process_memory_fraction",
35 "torch.npu.memory.set_per_process_memory_fraction",36 "torch.npu.memory.set_per_process_memory_fraction",
36 "torch.npu.random.manual_seed_all",37 "torch.npu.random.manual_seed_all",
37 "torch.npu.random.manual_seed",38 "torch.npu.random.manual_seed",
@@ -67,6 +68,7 @@ torch_c_binding_in_graph_functions_npu = dict.fromkeys(
67 "torch_npu._C._npu_resetPeakMemoryStats",68 "torch_npu._C._npu_resetPeakMemoryStats",
68 "torch_npu._C._npu_set_sync_debug_mode",69 "torch_npu._C._npu_set_sync_debug_mode",
69 "torch_npu._C._npu_setDevice",70 "torch_npu._C._npu_setDevice",
71+ "torch_npu._C._npu_getMemoryFraction",
70 "torch_npu._C._npu_setMemoryFraction",72 "torch_npu._C._npu_setMemoryFraction",
71 "torch_npu._C._npu_synchronize",73 "torch_npu._C._npu_synchronize",
72 "torch_npu._C._npu_resetAccumulatedMemoryStats",74 "torch_npu._C._npu_resetAccumulatedMemoryStats",
@@ -31,6 +31,7 @@ __all__ = [
31 "initial_seed",31 "initial_seed",
32 "caching_allocator_alloc",32 "caching_allocator_alloc",
33 "caching_allocator_delete",33 "caching_allocator_delete",
34+ "get_per_process_memory_fraction",
34 "set_per_process_memory_fraction",35 "set_per_process_memory_fraction",
35 "empty_cache",36 "empty_cache",
36 "empty_virt_addr_cache",37 "empty_virt_addr_cache",
@@ -18,6 +18,7 @@ from ._memory_viz import memory as _memory, segments as _segments
18__all__ = [18__all__ = [
19 "caching_allocator_alloc",19 "caching_allocator_alloc",
20 "caching_allocator_delete",20 "caching_allocator_delete",
21+ "get_per_process_memory_fraction",
21 "set_per_process_memory_fraction",22 "set_per_process_memory_fraction",
22 "empty_cache",23 "empty_cache",
23 "empty_virt_addr_cache",24 "empty_virt_addr_cache",
@@ -123,6 +124,21 @@ def caching_allocator_delete(mem_ptr):
123 torch_npu._C._npu_npuCachingAllocator_raw_delete(mem_ptr)124 torch_npu._C._npu_npuCachingAllocator_raw_delete(mem_ptr)
124 125 
125 126 
127+def get_per_process_memory_fraction(device=None) -> float:
128+ r"""Get memory fraction for a process.
129+ Args:
130+ device (torch.device or int, optional): selected device. If it is
131+ ``None`` the default NPU device is used.
132+ Returns:
133+ memory fraction, in range 0~1. Allowed memory equals total_memory * fraction.
134+ """
135+ _lazy_init()
136+ if device is None:
137+ device = torch_npu.npu.current_device()
138+ device = _get_device_index(device)
139+ return torch_npu._C._npu_getMemoryFraction(device)
140+ 
141+ 
126def set_per_process_memory_fraction(fraction, device=None) -> None:142def set_per_process_memory_fraction(fraction, device=None) -> None:
127 r"""Set memory fraction for a process.143 r"""Set memory fraction for a process.
128 The fraction is used to limit an caching allocator to allocated memory on a NPU device.144 The fraction is used to limit an caching allocator to allocated memory on a NPU device.