已开启
[Bug]: 全量 UT 在预编译 CustomOps、浮点归约和可选 TensorFlow 导入场景下失败 #358
hedongdong创建于  9月2日
hedongdong成员
9月2日 创建

Checklist

🐛 Describe the bug

PR #1313 使用全量 native wheel 执行 Debug 门禁时,先后暴露出 3 个全量 UT 隔离或稳定性问题,以及 1 个 Torch differentiable all-gather 反向梯度连续性问题。

1. CustomOps 缺失扩展用例依赖运行环境

失败用例:

tests/ut/platform/mindspore/custom_ops/test_custom_op_impl.py::TestCustomOpsLoading::test_missing_extension_does_not_jit_compile

Debug 构建使用:

bash build.sh --multicore all --shmem all --custom-ops on --strict on

hyper_parallel_custom_ops_ms.so 已成功构建并打入 wheel。用例本意是验证“预编译扩展缺失时不进行 JIT 编译”,但没有显式模拟扩展不存在,而是依赖安装环境中没有该 .so。当全量 native wheel 中存在可加载扩展时,import 成功,预期的 ImportError 不再发生。

处理方式:删除该环境敏感且无法稳定构造缺失场景的用例;保留 loader 成功、加载失败包装和并发模块保护等有效覆盖。

2. MoE parity 用例使用浮点精确相等

失败用例:

tests/ut/platform/torch/common/test_moe_megatron_parity.py::TestLoadBalanceLossMegatronParity::test_semantic_difference_documentation

该用例在 CPU 上手工构造 float32 softmax 和 top-k 概率归约,没有调用 HyperParallel 的生产实现,并将浮点归约结果与整数 token 数量做精确相等比较。不同 CPU 架构、向量化实现或归约顺序可能产生末位误差;同文件其他用例已经覆盖公式等价性和负载均衡方向。

处理方式:删除该说明性、重复且依赖浮点精确相等的用例,不改动业务实现。

3. Activation checkpoint UT 间接加载 TensorFlow 后 SIGSEGV

失败用例:

tests/ut/trainer/test_activation_checkpoint.py::TestActivationCheckpointSwapInputs::test_eager_checkpoint_wrappers_receive_swap_inputs

导入链:

_apply_activation_checkpointing
  -> _should_use_hf_native_gradient_checkpointing
  -> transformers.modeling_layers
  -> transformers.processing_utils
  -> transformers.video_utils
  -> transformers.image_transforms
  -> tensorflow
  -> tensorflow.python.platform.self_check.preload_check
  -> SIGSEGV

该用例只验证 eager checkpoint wrapper 的 swap_inputs 参数透传,却没有隔离 Hugging Face native gradient-checkpoint 探测路径。门禁环境安装了 TensorFlow,Transformers 对可选后端的模块初始化触发 TensorFlow native extension 加载并崩溃。

处理方式:在该组 UT 中 mock _should_use_hf_native_gradient_checkpointing() 返回 False,使参数透传测试不再加载无关的 Transformers/TensorFlow 后端。修复后 Debug 构建 #1346 的全量 UT 通过。

4. Torch differentiable all-gather 反向传入非连续 Tensor

失败用例:

tests/torch/accuracy/test_llama3_accuracy.py::test_llama3_tp_cp_fully_shard_accuracy

Debug 构建 #1346、#1347 和 #1348 在 Context Parallel/DTensor 的 backward 路径稳定出现:

partial_loss.backward(backward_seed)
  -> torch.distributed.nn.functional._AllGather.backward
  -> torch.distributed.nn.functional._AlltoAll.forward
  -> torch.distributed.all_to_all
RuntimeError: Tensors must be contiguous

根因如下:

  • TorchPlatform.differentiable_all_gather_concat() 使用 torch.distributed.nn.functional.all_gather() 保留可微语义;
  • HyperParallel 原实现只保证 all-gather 的前向输入连续;
  • concat 的反向可能向各个 all-gather 输出返回非连续梯度视图;
  • PyTorch 的 _AllGather.backward 在当前非 NCCL 路径中通过 list-based all-to-all 归约这些梯度,HCCL/PTA 要求传入 Tensor 连续,因此在通信调用处报错。

该问题不是 native adapter、symmetric-memory CMake 或 MegaMoE kernel 引入的编译问题,而是现有 Torch platform differentiable collective 的反向张量布局契约没有覆盖 HCCL 要求。

处理方式:

  • 在每个 differentiable all-gather 输出后增加 autograd identity;
  • 前向直接返回原 Tensor,不增加拷贝;
  • 反向将 grad_output 转为 contiguous 后再交给 PyTorch 原有 _AllGather.backward;
  • 不改变通信后端、进程组、rank 顺序和原有 collective 算法。

补充了 backward 梯度连续性 UT,并通过本地 2 进程 Gloo 前向/反向验证;NPU/HCCL 回归由 PR #1313 的 Debug 门禁继续验证。

Expected behavior

  • UT 不依赖 wheel 中可选 native 组件是否存在;需要缺失场景时应显式构造该场景。
  • 浮点测试不使用脆弱的精确相等断言,且不保留不覆盖生产实现的重复说明性用例。
  • 仅验证 checkpoint 参数透传的 UT 不加载无关的 Transformers/TensorFlow 后端。
  • differentiable_all_gather_concat() 保证传给后端反向 collective 的梯度 Tensor 连续,同时保持前向结果、rank 顺序和 autograd 语义不变。
  • 全量 tests/ut 可以完整执行,Torch Context Parallel NPU ST 可以完成 backward。

Additional context

Environment info

全量 UT(#1344):

Python: 3.10.20
pytest: 9.1.1
PyTorch: 2.9.0+cpu
torch_npu: 2.9.0.post5
Build: --multicore all --shmem all --custom-ops on --strict on

Torch NPU ST(#1348):

Python: 3.10.19
pytest: 6.2.5
CANN: 9.2.0
Test: test_llama3_tp_cp_fully_shard_accuracy
likedislike
hedongdong成员
9月2日 评论:

补充处理结论(MoE parity UT):

test_semantic_difference_documentation 仅在 CPU 上手工构造 float32 softmax 和 top-k 概率归约,没有调用 HyperParallel 的 _compute_load_balance_loss 生产实现。其 assertEqual(megatron_prob_total, 100) 还依赖浮点归约结果与整数精确相等,容易受实现和归约顺序影响;同文件已有公式等价性及负载均衡方向用例覆盖有效行为。

PR #1313 已在提交 90fb789f 中直接删除该说明性、重复用例,未改动业务实现。删除后该测试文件定向执行结果为 6 passed,提交钩子的 pylint、lizard 检查通过。

本 Issue 中另外两个失败继续保留跟踪。

likedislike
hedongdong成员
9月2日 评论:
    def test_eager_checkpoint_wrappers_receive_swap_inputs(self):
        """Eager full and selective wrappers should receive the configured value."""
        for mode in ("full", "selective"):
            for swap_inputs in (False, True):
                with self.subTest(mode=mode, swap_inputs=swap_inputs):
                    model = _DiscoveryModel()
                    with (
                        patch(
                            f"{_ACTIVATION_CHECKPOINT_MODULE}._should_use_hf_native_gradient_checkpointing",
                            return_value=False,
                        ),
                        patch(f"{_ACTIVATION_CHECKPOINT_MODULE}.ensure_profiler_ops_sac_ignored"),
                        patch(f"{_ACTIVATION_CHECKPOINT_MODULE}.ensure_fsdp_ops_sac_ignored"),
                    ):
                        _apply_activation_checkpointing(
                            model,
                            mode,
                            enable_compile=False,
                            swap_inputs=swap_inputs,
                        )

                    for block in self._wrapped_blocks(model):
                        self.assertIs(block.checkpoint_kwargs["swap_inputs"], swap_inputs)
likedislike
hedongdong成员
9月2日 评论:

补充处理结论(Torch Context Parallel NPU ST):

PR #1313 在修复并重新执行 Debug 门禁后,原有 activation-checkpoint UT 的 TensorFlow SIGSEGV 已消失:构建 #1346 的 UT_TEST 全量通过。随后 Ascend Torch ST 在以下用例中失败:

tests/torch/accuracy/test_llama3_accuracy.py::test_llama3_tp_cp_fully_shard_accuracy

该问题在构建 #1346 和重跑构建 #1347 中连续复现,rank 级错误为:

partial_loss.backward(backward_seed)
  -> torch.distributed.nn.functional._AllGather.backward
  -> torch.distributed.nn.functional._AlltoAll.forward
  -> torch.distributed.all_to_all
RuntimeError: Tensors must be contiguous

根因边界:

  • TorchPlatform.differentiable_all_gather_concat() 当前使用 torch.distributed.nn.functional.all_gather();
  • HyperParallel 在前向进入 all-gather 前对输入执行了 contiguous 处理,但 PyTorch 的 stock autograd 实现在反向中会把上游梯度拆成 tensor list,再通过 list-based all_to_all 完成归约;
  • 这些反向梯度分片不保证连续,当前 HCCL/PTA 环境会直接拒绝非连续 tensor,因此仅处理前向输入不能覆盖该路径;
  • 两轮失败均发生在 Context Parallel/DTensor 通信路径。PR #1313 的 native 构建、adapter 和 symmetric-memory CMake 修改不会加载或修改该运行路径;同批其余 5 个 Torch NPU ST 均通过。

建议修复方向:

  1. 在 Torch platform 的 differentiable all-gather 实现中保证反向通信输入连续;
  2. 优先使用 HyperParallel 自有 autograd wrapper,在 backward 中对梯度显式 contiguous 后执行 reduce-scatter/all-reduce,而不是依赖 PyTorch stock _AllGather.backward 的 list-based all-to-all;
  3. 补充 CPU/Gloo 的 autograd 正确性测试和 NPU/HCCL 的非连续梯度回归用例;
  4. 不降低 test_llama3_tp_cp_fully_shard_accuracy 的精度断言,也不通过下掉用例规避通信契约问题。

门禁证据:

likedislike
Hhedongdong成员
9月3日 修改了issue 的描述