Files
paddlepaddle--paddle/test/compat/test_paddle_cuda_apis.py
T
2026-07-13 12:40:42 +08:00

497 lines
19 KiB
Python

# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
import unittest
from unittest import TestCase
import paddle
def should_skip_tests():
"""
Check if tests should be skipped based on device availability.
Skip if neither CUDA, XPU, nor any custom device is available.
"""
# Check CUDA availability
cuda_available = paddle.is_compiled_with_cuda()
# Check XPU availability
xpu_available = paddle.is_compiled_with_xpu()
# Check custom device availability
custom_available = False
try:
custom_devices = paddle.device.get_all_custom_device_type()
if custom_devices:
for device_type in custom_devices:
if paddle.device.is_compiled_with_custom_device(device_type):
custom_available = True
break
except Exception:
custom_available = False
# Skip tests if no supported devices are available
return not (cuda_available or xpu_available or custom_available)
# Check if we should skip all tests
if should_skip_tests():
print(
"Skipping paddle.cuda API tests: No CUDA, XPU, or custom devices available"
)
sys.exit(0)
class TestCurrentDevice(TestCase):
def test_current_device_return_type(self):
"""Test that current_device returns an integer."""
device_id = paddle.cuda.current_device()
self.assertIsInstance(
device_id, int, "current_device should return an integer"
)
def test_current_device_non_negative(self):
"""Test that current_device returns a non-negative integer."""
device_id = paddle.cuda.current_device()
self.assertGreaterEqual(
device_id, 0, "current_device should return a non-negative integer"
)
def test_current_device_with_device_set(self):
"""Test current_device after setting device."""
if paddle.device.cuda.device_count() > 0:
# Test with CUDA device
original_device = paddle.device.get_device()
# Set to device 0 if available
paddle.device.set_device('gpu:0')
device_id = paddle.cuda.current_device()
self.assertEqual(
device_id, 0, "current_device should return 0 when gpu:0 is set"
)
# Restore original device
paddle.device.set_device(original_device)
class TestDeviceCount(TestCase):
def test_device_count_return_type(self):
"""Test that device_count returns an integer."""
count = paddle.cuda.device_count()
self.assertIsInstance(
count, int, "device_count should return an integer"
)
def test_device_count_non_negative(self):
"""Test that device_count returns a non-negative integer."""
count = paddle.cuda.device_count()
self.assertGreaterEqual(
count, 0, "device_count should return a non-negative integer"
)
class TestEmptyCache(TestCase):
def test_empty_cache_return_type(self):
"""Test that empty_cache returns None."""
result = paddle.cuda.empty_cache()
self.assertIsNone(result, "empty_cache should return None")
def test_empty_cache_no_exception(self):
"""Test that empty_cache does not raise any exceptions."""
try:
paddle.cuda.empty_cache()
except Exception as e:
self.fail(f"empty_cache raised an exception: {e}")
def test_empty_cache_with_memory_allocation(self):
"""Test that empty_cache works after memory allocation."""
if paddle.cuda.device_count() > 0:
# Get initial memory state
initial_memory = paddle.cuda.memory_allocated()
# Allocate some memory
tensor = paddle.randn([1000, 1000])
allocated_memory = paddle.cuda.memory_allocated()
# Verify that memory was actually allocated
self.assertGreater(
allocated_memory,
initial_memory,
"Memory should increase after tensor allocation",
)
# Delete tensor and empty cache
del tensor
paddle.cuda.empty_cache()
# Check memory after empty_cache
final_memory = paddle.cuda.memory_allocated()
# Memory should be reduced after empty_cache
# Note: We allow some tolerance as memory management may not free everything immediately
self.assertLessEqual(
final_memory,
allocated_memory,
"Memory should be reduced after empty_cache",
)
class TestIsInitialized(TestCase):
def test_is_initialized_return_type(self):
"""Test that is_initialized returns a boolean."""
result = paddle.cuda.is_initialized()
self.assertIsInstance(
result, bool, "is_initialized should return a boolean"
)
def test_is_initialized_no_exception(self):
"""Test that is_initialized does not raise any exceptions."""
try:
paddle.cuda.is_initialized()
except Exception as e:
self.fail(f"is_initialized raised an exception: {e}")
def test_is_initialized_with_device_availability(self):
"""Test that is_initialized returns True when devices are available."""
# This test checks if is_initialized correctly detects device compilation
# The result should be consistent with device availability checks
initialized = paddle.cuda.is_initialized()
# If any device is available, is_initialized should return True
cuda_available = paddle.is_compiled_with_cuda()
xpu_available = paddle.is_compiled_with_xpu()
# Check custom devices
custom_available = False
try:
custom_devices = paddle.device.get_all_custom_device_type()
if custom_devices:
for device_type in custom_devices:
if paddle.device.is_compiled_with_custom_device(
device_type
):
custom_available = True
break
except Exception:
custom_available = False
# is_initialized should return True if any device type is compiled
expected = cuda_available or xpu_available or custom_available
self.assertEqual(
initialized,
expected,
f"is_initialized should return {expected} when cuda={cuda_available}, xpu={xpu_available}, custom={custom_available}",
)
class TestMemoryAllocated(TestCase):
def test_memory_allocated_return_type(self):
"""Test that memory_allocated returns an integer."""
result = paddle.cuda.memory_allocated()
self.assertIsInstance(
result, int, "memory_allocated should return an integer"
)
def test_memory_allocated_non_negative(self):
"""Test that memory_allocated returns a non-negative integer."""
result = paddle.cuda.memory_allocated()
self.assertGreaterEqual(
result, 0, "memory_allocated should return a non-negative integer"
)
def test_memory_allocated_consistency(self):
"""Test that memory_allocated returns consistent results when called multiple times."""
result1 = paddle.cuda.memory_allocated()
result2 = paddle.cuda.memory_allocated()
# Memory should be the same or increase (but not decrease without explicit free)
self.assertGreaterEqual(
result2, result1 - 1024, "memory_allocated should be consistent"
)
def test_memory_allocated_with_device_param(self):
"""Test that memory_allocated works with device parameter."""
if paddle.cuda.device_count() > 0:
# Test with device index
result_index = paddle.cuda.memory_allocated(0)
self.assertIsInstance(
result_index,
int,
"memory_allocated should return an integer with device index",
)
self.assertGreaterEqual(
result_index,
0,
"memory_allocated should return non-negative with device index",
)
def test_memory_allocated_no_exception(self):
"""Test that memory_allocated does not raise any exceptions."""
try:
paddle.cuda.memory_allocated()
except Exception as e:
self.fail(f"memory_allocated raised an exception: {e}")
class TestMemoryReserved(TestCase):
def test_memory_reserved_return_type(self):
"""Test that memory_reserved returns an integer."""
result = paddle.cuda.memory_reserved()
self.assertIsInstance(
result, int, "memory_reserved should return an integer"
)
def test_memory_reserved_non_negative(self):
"""Test that memory_reserved returns a non-negative integer."""
result = paddle.cuda.memory_reserved()
self.assertGreaterEqual(
result, 0, "memory_reserved should return a non-negative integer"
)
def test_memory_reserved_consistency(self):
"""Test that memory_reserved returns consistent results when called multiple times."""
result1 = paddle.cuda.memory_reserved()
result2 = paddle.cuda.memory_reserved()
# Reserved memory should be the same or increase (but not decrease without explicit free)
self.assertGreaterEqual(
result2, result1 - 1024, "memory_reserved should be consistent"
)
def test_memory_reserved_with_device_param(self):
"""Test that memory_reserved works with device parameter."""
if paddle.cuda.device_count() > 0:
# Test with device index
result_index = paddle.cuda.memory_reserved(0)
self.assertIsInstance(
result_index,
int,
"memory_reserved should return an integer with device index",
)
self.assertGreaterEqual(
result_index,
0,
"memory_reserved should return non-negative with device index",
)
def test_memory_reserved_no_exception(self):
"""Test that memory_reserved does not raise any exceptions."""
try:
paddle.cuda.memory_reserved()
except Exception as e:
self.fail(f"memory_reserved raised an exception: {e}")
def test_memory_reserved_vs_allocated(self):
"""Test that memory_reserved is greater than or equal to memory_allocated."""
if paddle.cuda.is_initialized():
reserved = paddle.cuda.memory_reserved()
allocated = paddle.cuda.memory_allocated()
self.assertGreaterEqual(
reserved,
allocated,
"memory_reserved should be >= memory_allocated",
)
class TestSetDevice(TestCase):
def test_set_device_return_type(self):
"""Test that set_device returns None."""
if paddle.is_compiled_with_cuda() and paddle.cuda.device_count() > 0:
result = paddle.cuda.set_device(0)
self.assertIsNone(result, "set_device should return None")
def test_set_device_no_exception(self):
"""Test that set_device does not raise any exceptions."""
if paddle.is_compiled_with_cuda() and paddle.cuda.device_count() > 0:
try:
paddle.cuda.set_device(0)
except Exception as e:
self.fail(f"set_device raised an exception: {e}")
def test_set_device_with_int_param(self):
"""Test that set_device works with integer parameter."""
if paddle.is_compiled_with_cuda() and paddle.cuda.device_count() > 0:
try:
# Test with device index 0
paddle.cuda.set_device(0)
# Verify device was set correctly
current_device = paddle.cuda.current_device()
self.assertEqual(
current_device, 0, "set_device should set device to 0"
)
except Exception as e:
self.fail(
f"set_device with int parameter raised an exception: {e}"
)
def test_set_device_int_after_cpu_place(self):
"""Test int parameter after switching the expected place to CPU."""
if not (
paddle.is_compiled_with_cuda() and paddle.cuda.device_count() > 0
):
return
original_device = paddle.device.get_device()
try:
paddle.device.set_device('cpu')
paddle.cuda.set_device(0)
self.assertEqual(
paddle.cuda.current_device(),
0,
'cuda.set_device(0) should select GPU 0 even when the '
'current place is CPU',
)
except Exception as e:
self.fail(
f'cuda.set_device(int) after a CPU place raised an '
f'exception: {e}'
)
finally:
paddle.device.set_device(original_device)
def test_set_device_with_str_param(self):
"""Test that set_device works with string parameter."""
if paddle.is_compiled_with_cuda() and paddle.cuda.device_count() > 0:
try:
# Test with device string
paddle.cuda.set_device('gpu:0')
# Verify device was set correctly
current_device = paddle.cuda.current_device()
self.assertEqual(
current_device,
0,
"set_device should set device to 0 with 'gpu:0'",
)
paddle.cuda.set_device('cuda:0')
current_device = paddle.cuda.current_device()
self.assertEqual(
current_device,
0,
"set_device should set device to 0 with 'cuda:0'",
)
# bare 'gpu' / 'cuda' select the default GPU without raising
paddle.cuda.set_device('gpu')
paddle.cuda.set_device('cuda')
except Exception as e:
self.fail(
f"set_device with string parameter raised an exception: {e}"
)
def test_set_device_with_cuda_place_param(self):
"""Test that set_device works with CUDAPlace parameter."""
if paddle.is_compiled_with_cuda() and paddle.cuda.device_count() > 0:
try:
# Test with CUDAPlace
place = paddle.CUDAPlace(0)
paddle.cuda.set_device(place)
# Verify device was set correctly
current_device = paddle.cuda.current_device()
self.assertEqual(
current_device,
0,
"set_device should set device to 0 with CUDAPlace",
)
except Exception as e:
self.fail(
f"set_device with CUDAPlace parameter raised an exception: {e}"
)
def test_set_device_with_xpu_place_param(self):
"""paddle.cuda.set_device rejects an XPUPlace; use paddle.device.set_device."""
if paddle.is_compiled_with_xpu():
with self.assertRaises(ValueError):
paddle.cuda.set_device(paddle.XPUPlace(0))
def test_set_device_with_xpu_str_param(self):
"""paddle.cuda.set_device rejects an 'xpu:*' string; use paddle.device.set_device."""
with self.assertRaises(ValueError):
paddle.cuda.set_device('xpu:0')
def test_set_device_with_custom_place_param(self):
"""paddle.cuda.set_device rejects a CustomPlace; use paddle.device.set_device."""
custom_devices = paddle.device.get_all_custom_device_type()
if custom_devices:
with self.assertRaises(ValueError):
paddle.cuda.set_device(paddle.CustomPlace(custom_devices[0], 0))
def test_set_device_with_custom_str_param(self):
"""paddle.cuda.set_device rejects a custom-device string; use paddle.device.set_device."""
with self.assertRaises(ValueError):
paddle.cuda.set_device('npu:0')
def test_set_device_invalid_param(self):
"""Test that set_device raises ValueError for invalid parameter types."""
with self.assertRaises(ValueError) as context:
paddle.cuda.set_device(3.14) # Invalid float parameter
self.assertIn("Unsupported device type", str(context.exception))
with self.assertRaises(ValueError) as context:
paddle.cuda.set_device([0]) # Invalid list parameter
self.assertIn("Unsupported device type", str(context.exception))
class TestBf16Supported(unittest.TestCase):
def test_is_bf16_supported(self):
self.assertIsInstance(paddle.cuda.is_bf16_supported(), bool)
self.assertIsInstance(paddle.device.is_bf16_supported(), bool)
self.assertIsInstance(paddle.device.is_bf16_supported(True), bool)
self.assertIsInstance(paddle.cuda.is_bf16_supported(False), bool)
if should_skip_tests():
self.assertFalse(paddle.cuda.is_bf16_supported())
self.assertFalse(paddle.device.is_bf16_supported())
class TestManualSeed(unittest.TestCase):
def test_device_manual_seed(self):
paddle.device.manual_seed(102)
x1 = paddle.randn([2, 3])
paddle.device.manual_seed(999)
x2 = paddle.randn([2, 3])
paddle.device.manual_seed(102)
x3 = paddle.randn([2, 3])
self.assertTrue(
paddle.equal_all(x1, x3),
"Random outputs should be identical with the same seed",
)
self.assertFalse(
paddle.equal_all(x1, x2),
"Random outputs should differ with different seeds",
)
def test_cuda_manual_seed(self):
paddle.cuda.manual_seed(102)
x1 = paddle.randn([2, 3], dtype='float32')
paddle.cuda.manual_seed(999)
x2 = paddle.randn([2, 3], dtype='float32')
paddle.cuda.manual_seed(102)
x3 = paddle.randn([2, 3], dtype='float32')
self.assertTrue(
paddle.equal_all(x1, x3),
"Random outputs should be identical with the same seed",
)
self.assertFalse(
paddle.equal_all(x1, x2),
"Random outputs should differ with different seeds",
)
if __name__ == '__main__':
unittest.main()