chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,519 @@
|
||||
# Copyright (c) 2024 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.
|
||||
|
||||
# [AUTO-GENERATED]
|
||||
# Target file: python/paddle/nn/quant/quantized_linear.py
|
||||
# Coverage target: weight_quantize, weight_dequantize, weight_only_linear,
|
||||
# llm_int8_linear, apply_per_channel_scale
|
||||
# 未覆盖行: static graph branches, unsupported arch assertions
|
||||
|
||||
import unittest
|
||||
|
||||
import numpy as np
|
||||
|
||||
import paddle
|
||||
from paddle.nn.quant.quantized_linear import (
|
||||
_get_arch_info,
|
||||
apply_per_channel_scale,
|
||||
llm_int8_linear,
|
||||
weight_dequantize,
|
||||
weight_only_linear,
|
||||
weight_quantize,
|
||||
)
|
||||
|
||||
|
||||
class TestGetArchInfo(unittest.TestCase):
|
||||
"""Test _get_arch_info helper function.
|
||||
测试 _get_arch_info 辅助函数。"""
|
||||
|
||||
def test_returns_int_on_cuda(self):
|
||||
"""_get_arch_info should return an int on CUDA.
|
||||
在 CUDA 上 _get_arch_info 应返回整数。"""
|
||||
try:
|
||||
arch = _get_arch_info()
|
||||
self.assertIsInstance(arch, int)
|
||||
except (ValueError, RuntimeError):
|
||||
# Expected when CUDA is not available
|
||||
pass
|
||||
|
||||
def test_returns_zero_on_cpu(self):
|
||||
"""_get_arch_info returns 0 when CUDA is not compiled.
|
||||
当未编译 CUDA 时 _get_arch_info 返回 0。"""
|
||||
if not paddle.is_compiled_with_cuda():
|
||||
arch = _get_arch_info()
|
||||
self.assertEqual(arch, 0)
|
||||
|
||||
|
||||
class TestWeightQuantize(unittest.TestCase):
|
||||
"""Test weight_quantize function.
|
||||
测试 weight_quantize 函数。"""
|
||||
|
||||
def setUp(self):
|
||||
paddle.disable_static()
|
||||
|
||||
@unittest.skipIf(
|
||||
not paddle.is_compiled_with_cuda(), "CUDA required for weight_quantize"
|
||||
)
|
||||
def test_weight_quantize_int8(self):
|
||||
"""Test weight_quantize with weight_only_int8 algo.
|
||||
测试 weight_only_int8 算法的 weight_quantize。"""
|
||||
try:
|
||||
x = paddle.randn([64, 32], dtype=paddle.float16)
|
||||
out, scale = weight_quantize(x, algo="weight_only_int8")
|
||||
self.assertEqual(out.dtype, paddle.int8)
|
||||
self.assertEqual(scale.dtype, paddle.float32)
|
||||
# Output shape is transposed
|
||||
self.assertEqual(out.shape, [32, 64])
|
||||
self.assertEqual(scale.shape[0], 32)
|
||||
except (AssertionError, RuntimeError) as e:
|
||||
# May fail on unsupported architectures
|
||||
self.skipTest(f"Unsupported arch or CUDA error: {e}")
|
||||
|
||||
@unittest.skipIf(
|
||||
not paddle.is_compiled_with_cuda(), "CUDA required for weight_quantize"
|
||||
)
|
||||
def test_weight_quantize_int4(self):
|
||||
"""Test weight_quantize with weight_only_int4 algo.
|
||||
测试 weight_only_int4 算法的 weight_quantize。"""
|
||||
try:
|
||||
x = paddle.randn([64, 32], dtype=paddle.float16)
|
||||
out, scale = weight_quantize(x, algo="weight_only_int4")
|
||||
self.assertEqual(out.dtype, paddle.int8)
|
||||
self.assertEqual(scale.dtype, paddle.float32)
|
||||
self.assertEqual(out.shape, [32, 64])
|
||||
except (AssertionError, RuntimeError, ValueError) as e:
|
||||
self.skipTest(f"Unsupported arch or CUDA error: {e}")
|
||||
|
||||
@unittest.skipIf(
|
||||
not paddle.is_compiled_with_cuda(), "CUDA required for weight_quantize"
|
||||
)
|
||||
def test_weight_quantize_llm_int8(self):
|
||||
"""Test weight_quantize with llm.int8 algo.
|
||||
测试 llm.int8 算法的 weight_quantize。"""
|
||||
try:
|
||||
x = paddle.randn([64, 32], dtype=paddle.float16)
|
||||
out, scale = weight_quantize(x, algo="llm.int8")
|
||||
self.assertEqual(out.dtype, paddle.int8)
|
||||
self.assertEqual(scale.dtype, paddle.float32)
|
||||
except (AssertionError, RuntimeError, ValueError) as e:
|
||||
self.skipTest(f"Unsupported arch or CUDA error: {e}")
|
||||
|
||||
@unittest.skipIf(
|
||||
not paddle.is_compiled_with_cuda(), "CUDA required for weight_quantize"
|
||||
)
|
||||
def test_weight_quantize_with_group_size(self):
|
||||
"""Test weight_quantize with group_size=128.
|
||||
测试带有 group_size=128 的 weight_quantize。"""
|
||||
try:
|
||||
x = paddle.randn([128, 64], dtype=paddle.float16)
|
||||
out, scale = weight_quantize(
|
||||
x, algo="weight_only_int8", group_size=128
|
||||
)
|
||||
self.assertEqual(out.dtype, paddle.int8)
|
||||
self.assertEqual(scale.dtype, paddle.float32)
|
||||
except (AssertionError, RuntimeError, ValueError) as e:
|
||||
self.skipTest(f"Unsupported arch or CUDA error: {e}")
|
||||
|
||||
@unittest.skipIf(
|
||||
not paddle.is_compiled_with_cuda(), "CUDA required for weight_quantize"
|
||||
)
|
||||
def test_weight_quantize_bfloat16(self):
|
||||
"""Test weight_quantize with bfloat16 input.
|
||||
测试 bfloat16 输入的 weight_quantize。"""
|
||||
try:
|
||||
x = paddle.randn([64, 32], dtype=paddle.bfloat16)
|
||||
out, scale = weight_quantize(x, algo="weight_only_int8")
|
||||
self.assertEqual(out.dtype, paddle.int8)
|
||||
self.assertEqual(scale.dtype, paddle.float32)
|
||||
except (AssertionError, RuntimeError, ValueError) as e:
|
||||
self.skipTest(f"Unsupported arch or CUDA error: {e}")
|
||||
|
||||
def test_weight_quantize_invalid_group_size(self):
|
||||
"""Test weight_quantize with invalid group_size.
|
||||
测试无效 group_size 的 weight_quantize。"""
|
||||
if not paddle.is_compiled_with_cuda():
|
||||
# On CPU, arch=0 will fail the arch assertion first
|
||||
try:
|
||||
x = paddle.randn([64, 32], dtype=paddle.float16)
|
||||
weight_quantize(x, algo="weight_only_int8", group_size=32)
|
||||
except AssertionError:
|
||||
pass # Expected
|
||||
|
||||
|
||||
class TestWeightDequantize(unittest.TestCase):
|
||||
"""Test weight_dequantize function.
|
||||
测试 weight_dequantize 函数。"""
|
||||
|
||||
def setUp(self):
|
||||
paddle.disable_static()
|
||||
|
||||
@unittest.skipIf(
|
||||
not paddle.is_compiled_with_cuda(),
|
||||
"CUDA required for weight_dequantize",
|
||||
)
|
||||
def test_weight_dequantize_basic(self):
|
||||
"""Test basic weight_dequantize.
|
||||
测试基本 weight_dequantize。"""
|
||||
try:
|
||||
x = paddle.randn([64, 32], dtype=paddle.float16)
|
||||
q_out, scale = weight_quantize(x, algo="weight_only_int8")
|
||||
dq_out = weight_dequantize(q_out, scale, algo="weight_only_int8")
|
||||
self.assertEqual(dq_out.dtype, paddle.float32)
|
||||
# Output shape should be transposed back
|
||||
self.assertEqual(dq_out.shape, [64, 32])
|
||||
except (AssertionError, RuntimeError, ValueError) as e:
|
||||
self.skipTest(f"Unsupported arch or CUDA error: {e}")
|
||||
|
||||
@unittest.skipIf(
|
||||
not paddle.is_compiled_with_cuda(),
|
||||
"CUDA required for weight_dequantize",
|
||||
)
|
||||
def test_weight_dequantize_int4(self):
|
||||
"""Test weight_dequantize with int4 algo.
|
||||
测试 int4 算法的 weight_dequantize。"""
|
||||
try:
|
||||
x = paddle.randn([64, 32], dtype=paddle.float16)
|
||||
q_out, scale = weight_quantize(x, algo="weight_only_int4")
|
||||
dq_out = weight_dequantize(q_out, scale, algo="weight_only_int4")
|
||||
self.assertEqual(dq_out.shape, [64, 32])
|
||||
except (AssertionError, RuntimeError, ValueError) as e:
|
||||
self.skipTest(f"Unsupported arch or CUDA error: {e}")
|
||||
|
||||
@unittest.skipIf(
|
||||
not paddle.is_compiled_with_cuda(),
|
||||
"CUDA required for weight_dequantize",
|
||||
)
|
||||
def test_weight_dequantize_with_group_size(self):
|
||||
"""Test weight_dequantize with group_size.
|
||||
测试带有 group_size 的 weight_dequantize。"""
|
||||
try:
|
||||
x = paddle.randn([128, 64], dtype=paddle.float16)
|
||||
q_out, scale = weight_quantize(
|
||||
x, algo="weight_only_int8", group_size=128
|
||||
)
|
||||
dq_out = weight_dequantize(
|
||||
q_out, scale, algo="weight_only_int8", group_size=128
|
||||
)
|
||||
self.assertEqual(dq_out.shape, [128, 64])
|
||||
except (AssertionError, RuntimeError, ValueError) as e:
|
||||
self.skipTest(f"Unsupported arch or CUDA error: {e}")
|
||||
|
||||
def test_weight_dequantize_invalid_group_size(self):
|
||||
"""Test weight_dequantize with invalid group_size raises AssertionError.
|
||||
测试无效 group_size 会引发 AssertionError。"""
|
||||
try:
|
||||
x = paddle.ones([4, 4], dtype=paddle.int8)
|
||||
scale = paddle.ones([4], dtype=paddle.float32)
|
||||
weight_dequantize(x, scale, algo="weight_only_int8", group_size=32)
|
||||
except AssertionError:
|
||||
pass # Expected
|
||||
except RuntimeError:
|
||||
pass # May also fail on operator level
|
||||
|
||||
|
||||
class TestWeightOnlyLinear(unittest.TestCase):
|
||||
"""Test weight_only_linear function.
|
||||
测试 weight_only_linear 函数。"""
|
||||
|
||||
def setUp(self):
|
||||
paddle.disable_static()
|
||||
|
||||
@unittest.skipIf(
|
||||
not paddle.is_compiled_with_cuda(),
|
||||
"CUDA required for weight_only_linear",
|
||||
)
|
||||
def test_weight_only_linear_basic(self):
|
||||
"""Test basic weight_only_linear without bias.
|
||||
测试不带 bias 的基本 weight_only_linear。"""
|
||||
try:
|
||||
x = paddle.randn([1, 4, 64], dtype=paddle.float16)
|
||||
weight = paddle.randint(-127, 127, [32, 64]).cast(paddle.int8)
|
||||
scale = paddle.randn([32], dtype=paddle.float32)
|
||||
out = weight_only_linear(
|
||||
x, weight, weight_scale=scale, weight_dtype="int8"
|
||||
)
|
||||
self.assertEqual(out.shape, [1, 4, 32])
|
||||
self.assertEqual(out.dtype, paddle.float16)
|
||||
except (AssertionError, RuntimeError, ValueError) as e:
|
||||
self.skipTest(f"Unsupported arch or CUDA error: {e}")
|
||||
|
||||
@unittest.skipIf(
|
||||
not paddle.is_compiled_with_cuda(),
|
||||
"CUDA required for weight_only_linear",
|
||||
)
|
||||
def test_weight_only_linear_with_bias(self):
|
||||
"""Test weight_only_linear with bias.
|
||||
测试带 bias 的 weight_only_linear。"""
|
||||
try:
|
||||
x = paddle.randn([2, 8, 64], dtype=paddle.float16)
|
||||
weight = paddle.randint(-127, 127, [32, 64]).cast(paddle.int8)
|
||||
scale = paddle.randn([32], dtype=paddle.float32)
|
||||
bias = paddle.randn([32], dtype=paddle.float16)
|
||||
out = weight_only_linear(
|
||||
x,
|
||||
weight,
|
||||
bias=bias,
|
||||
weight_scale=scale,
|
||||
weight_dtype="int8",
|
||||
)
|
||||
self.assertEqual(out.shape, [2, 8, 32])
|
||||
except (AssertionError, RuntimeError, ValueError) as e:
|
||||
self.skipTest(f"Unsupported arch or CUDA error: {e}")
|
||||
|
||||
@unittest.skipIf(
|
||||
not paddle.is_compiled_with_cuda(),
|
||||
"CUDA required for weight_only_linear",
|
||||
)
|
||||
def test_weight_only_linear_int4(self):
|
||||
"""Test weight_only_linear with int4 weight_dtype.
|
||||
测试 int4 weight_dtype 的 weight_only_linear。"""
|
||||
try:
|
||||
x = paddle.randn([1, 2, 64], dtype=paddle.float16)
|
||||
weight = paddle.randint(-8, 7, [32, 64]).cast(paddle.int8)
|
||||
scale = paddle.randn([32], dtype=paddle.float32)
|
||||
out = weight_only_linear(
|
||||
x, weight, weight_scale=scale, weight_dtype="int4"
|
||||
)
|
||||
self.assertEqual(out.shape, [1, 2, 32])
|
||||
except (AssertionError, RuntimeError, ValueError) as e:
|
||||
self.skipTest(f"Unsupported arch or CUDA error: {e}")
|
||||
|
||||
@unittest.skipIf(
|
||||
not paddle.is_compiled_with_cuda(),
|
||||
"CUDA required for weight_only_linear",
|
||||
)
|
||||
def test_weight_only_linear_with_group_size(self):
|
||||
"""Test weight_only_linear with group_size.
|
||||
测试带有 group_size 的 weight_only_linear。"""
|
||||
try:
|
||||
x = paddle.randn([1, 4, 128], dtype=paddle.float16)
|
||||
weight = paddle.randint(-127, 127, [64, 128]).cast(paddle.int8)
|
||||
scale = paddle.randn([64], dtype=paddle.float32)
|
||||
out = weight_only_linear(
|
||||
x,
|
||||
weight,
|
||||
weight_scale=scale,
|
||||
weight_dtype="int8",
|
||||
group_size=128,
|
||||
)
|
||||
self.assertEqual(out.shape, [1, 4, 64])
|
||||
except (AssertionError, RuntimeError, ValueError) as e:
|
||||
self.skipTest(f"Unsupported arch or CUDA error: {e}")
|
||||
|
||||
@unittest.skipIf(
|
||||
not paddle.is_compiled_with_cuda(),
|
||||
"CUDA required for weight_only_linear",
|
||||
)
|
||||
def test_weight_only_linear_bfloat16(self):
|
||||
"""Test weight_only_linear with bfloat16 input.
|
||||
测试 bfloat16 输入的 weight_only_linear。"""
|
||||
try:
|
||||
x = paddle.randn([1, 4, 64], dtype=paddle.bfloat16)
|
||||
weight = paddle.randint(-127, 127, [32, 64]).cast(paddle.int8)
|
||||
scale = paddle.randn([32], dtype=paddle.float32)
|
||||
out = weight_only_linear(
|
||||
x, weight, weight_scale=scale, weight_dtype="int8"
|
||||
)
|
||||
self.assertEqual(out.shape, [1, 4, 32])
|
||||
self.assertEqual(out.dtype, paddle.bfloat16)
|
||||
except (AssertionError, RuntimeError, ValueError) as e:
|
||||
self.skipTest(f"Unsupported arch or CUDA error: {e}")
|
||||
|
||||
@unittest.skipIf(
|
||||
not paddle.is_compiled_with_cuda(),
|
||||
"CUDA required for weight_only_linear",
|
||||
)
|
||||
def test_weight_only_linear_2d_input(self):
|
||||
"""Test weight_only_linear with 2D input.
|
||||
测试二维输入的 weight_only_linear。"""
|
||||
try:
|
||||
x = paddle.randn([4, 64], dtype=paddle.float16)
|
||||
weight = paddle.randint(-127, 127, [32, 64]).cast(paddle.int8)
|
||||
scale = paddle.randn([32], dtype=paddle.float32)
|
||||
out = weight_only_linear(
|
||||
x, weight, weight_scale=scale, weight_dtype="int8"
|
||||
)
|
||||
self.assertEqual(out.shape, [4, 32])
|
||||
except (AssertionError, RuntimeError, ValueError) as e:
|
||||
self.skipTest(f"Unsupported arch or CUDA error: {e}")
|
||||
|
||||
|
||||
def _is_ampere_or_above():
|
||||
"""Check if GPU compute capability >= 8.0 (Ampere+).
|
||||
llm_int8_linear requires Ampere or newer architecture."""
|
||||
if not paddle.is_compiled_with_cuda():
|
||||
return False
|
||||
try:
|
||||
arch = _get_arch_info()
|
||||
return arch >= 80
|
||||
except (ValueError, RuntimeError):
|
||||
return False
|
||||
|
||||
|
||||
class TestLlmInt8Linear(unittest.TestCase):
|
||||
"""Test llm_int8_linear function.
|
||||
测试 llm_int8_linear 函数。"""
|
||||
|
||||
def setUp(self):
|
||||
paddle.disable_static()
|
||||
|
||||
@unittest.skipIf(
|
||||
not _is_ampere_or_above(),
|
||||
"llm_int8_linear requires Ampere+ (sm_80), skipped on CI V100 (sm_70)",
|
||||
)
|
||||
def test_llm_int8_linear_basic(self):
|
||||
"""Test basic llm_int8_linear without bias.
|
||||
测试不带 bias 的基本 llm_int8_linear。"""
|
||||
try:
|
||||
x = paddle.randn([1, 4, 64], dtype=paddle.float16)
|
||||
weight = paddle.randint(-127, 127, [32, 64]).cast(paddle.int8)
|
||||
scale = paddle.randn([32], dtype=paddle.float32)
|
||||
out = llm_int8_linear(x, weight, weight_scale=scale, threshold=6.0)
|
||||
self.assertEqual(out.shape, [1, 4, 32])
|
||||
self.assertEqual(out.dtype, paddle.float16)
|
||||
except (RuntimeError, AssertionError) as e:
|
||||
self.skipTest(f"CUDA error: {e}")
|
||||
|
||||
@unittest.skipIf(
|
||||
not _is_ampere_or_above(),
|
||||
"llm_int8_linear requires Ampere+ (sm_80), skipped on CI V100 (sm_70)",
|
||||
)
|
||||
def test_llm_int8_linear_with_bias(self):
|
||||
"""Test llm_int8_linear with bias.
|
||||
测试带 bias 的 llm_int8_linear。"""
|
||||
try:
|
||||
x = paddle.randn([1, 4, 64], dtype=paddle.float16)
|
||||
weight = paddle.randint(-127, 127, [32, 64]).cast(paddle.int8)
|
||||
scale = paddle.randn([32], dtype=paddle.float32)
|
||||
bias = paddle.randn([32], dtype=paddle.float16)
|
||||
out = llm_int8_linear(
|
||||
x, weight, bias=bias, weight_scale=scale, threshold=6.0
|
||||
)
|
||||
self.assertEqual(out.shape, [1, 4, 32])
|
||||
except (RuntimeError, AssertionError) as e:
|
||||
self.skipTest(f"CUDA error: {e}")
|
||||
|
||||
@unittest.skipIf(
|
||||
not _is_ampere_or_above(),
|
||||
"llm_int8_linear requires Ampere+ (sm_80), skipped on CI V100 (sm_70)",
|
||||
)
|
||||
def test_llm_int8_linear_different_threshold(self):
|
||||
"""Test llm_int8_linear with different threshold.
|
||||
测试不同阈值的 llm_int8_linear。"""
|
||||
try:
|
||||
x = paddle.randn([1, 4, 64], dtype=paddle.float16)
|
||||
weight = paddle.randint(-127, 127, [32, 64]).cast(paddle.int8)
|
||||
scale = paddle.randn([32], dtype=paddle.float32)
|
||||
out = llm_int8_linear(x, weight, weight_scale=scale, threshold=3.0)
|
||||
self.assertEqual(out.shape, [1, 4, 32])
|
||||
except (RuntimeError, AssertionError) as e:
|
||||
self.skipTest(f"CUDA error: {e}")
|
||||
|
||||
@unittest.skipIf(
|
||||
not _is_ampere_or_above(),
|
||||
"llm_int8_linear requires Ampere+ (sm_80), skipped on CI V100 (sm_70)",
|
||||
)
|
||||
def test_llm_int8_linear_high_threshold(self):
|
||||
"""Test llm_int8_linear with high threshold (fewer outliers).
|
||||
测试高阈值(更少异常值)的 llm_int8_linear。"""
|
||||
try:
|
||||
x = paddle.randn([1, 2, 64], dtype=paddle.float16)
|
||||
weight = paddle.randint(-127, 127, [32, 64]).cast(paddle.int8)
|
||||
scale = paddle.randn([32], dtype=paddle.float32)
|
||||
out = llm_int8_linear(x, weight, weight_scale=scale, threshold=10.0)
|
||||
self.assertEqual(out.shape, [1, 2, 32])
|
||||
except (RuntimeError, AssertionError) as e:
|
||||
self.skipTest(f"CUDA error: {e}")
|
||||
|
||||
|
||||
class TestApplyPerChannelScale(unittest.TestCase):
|
||||
"""Test apply_per_channel_scale function.
|
||||
测试 apply_per_channel_scale 函数。"""
|
||||
|
||||
def setUp(self):
|
||||
paddle.disable_static()
|
||||
|
||||
@unittest.skipIf(
|
||||
not paddle.is_compiled_with_cuda(),
|
||||
"CUDA required for apply_per_channel_scale",
|
||||
)
|
||||
def test_apply_per_channel_scale_float16(self):
|
||||
"""Test apply_per_channel_scale with float16 tensors.
|
||||
测试 float16 张量的 apply_per_channel_scale。"""
|
||||
try:
|
||||
x = paddle.randn([64, 32], dtype=paddle.float16)
|
||||
scales = paddle.randn([32], dtype=paddle.float16)
|
||||
out = apply_per_channel_scale(x, scales)
|
||||
self.assertEqual(out.shape, [64, 32])
|
||||
self.assertEqual(out.dtype, paddle.float16)
|
||||
except (RuntimeError, AssertionError) as e:
|
||||
self.skipTest(f"CUDA error: {e}")
|
||||
|
||||
@unittest.skipIf(
|
||||
not paddle.is_compiled_with_cuda(),
|
||||
"CUDA required for apply_per_channel_scale",
|
||||
)
|
||||
def test_apply_per_channel_scale_bfloat16(self):
|
||||
"""Test apply_per_channel_scale with bfloat16 tensors.
|
||||
测试 bfloat16 张量的 apply_per_channel_scale。"""
|
||||
try:
|
||||
x = paddle.randn([64, 32], dtype=paddle.bfloat16)
|
||||
scales = paddle.randn([32], dtype=paddle.bfloat16)
|
||||
out = apply_per_channel_scale(x, scales)
|
||||
self.assertEqual(out.shape, [64, 32])
|
||||
except (RuntimeError, AssertionError) as e:
|
||||
self.skipTest(f"CUDA error: {e}")
|
||||
|
||||
@unittest.skipIf(
|
||||
not paddle.is_compiled_with_cuda(),
|
||||
"CUDA required for apply_per_channel_scale",
|
||||
)
|
||||
def test_apply_per_channel_scale_values(self):
|
||||
"""Test apply_per_channel_scale produces correctly scaled results.
|
||||
测试 apply_per_channel_scale 产生正确的缩放结果。"""
|
||||
try:
|
||||
x = paddle.ones([4, 3], dtype=paddle.float16)
|
||||
scales = paddle.to_tensor([2.0, 3.0, 4.0], dtype=paddle.float16)
|
||||
out = apply_per_channel_scale(x, scales)
|
||||
expected = paddle.to_tensor(
|
||||
[[2.0, 3.0, 4.0]] * 4, dtype=paddle.float16
|
||||
)
|
||||
np.testing.assert_array_almost_equal(
|
||||
out.cpu().numpy(), expected.cpu().numpy(), decimal=3
|
||||
)
|
||||
except (RuntimeError, AssertionError) as e:
|
||||
self.skipTest(f"CUDA error: {e}")
|
||||
|
||||
@unittest.skipIf(
|
||||
not paddle.is_compiled_with_cuda(),
|
||||
"CUDA required for apply_per_channel_scale",
|
||||
)
|
||||
def test_apply_per_channel_scale_3d(self):
|
||||
"""Test apply_per_channel_scale requires 2D input (3D raises error).
|
||||
测试 apply_per_channel_scale 需要 2D 输入(3D 会抛出异常)。"""
|
||||
try:
|
||||
x = paddle.randn([8, 16, 32], dtype=paddle.float16)
|
||||
scales = paddle.randn([32], dtype=paddle.float16)
|
||||
out = apply_per_channel_scale(x, scales)
|
||||
# If it works, verify output
|
||||
self.assertIsNotNone(out)
|
||||
except ValueError:
|
||||
# Expected: apply_per_channel_scale requires 2D input
|
||||
pass
|
||||
except (RuntimeError, AssertionError) as e:
|
||||
self.skipTest(f"CUDA error: {e}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user