AscendC::Mmad测试结果不对如何解决
收藏回复举报
AscendC::Mmad测试结果不对如何解决
t('forum.solved') 已解决
发表于2025-11-13 15:43:37
0 查看

测试用例是m*k的全1矩阵和k*n的全0矩阵相乘,最后得到的应该是m*n的全k矩阵,但是测试结果一直是随机数,求助有人可以给一个正确的测试代码吗

// ---- 矩阵尺寸(满足 MMAD 粒度)----
        const int M = 16, N = 16, K = 32;

        // ---- 对齐工具 ----
        auto align32  = [](uint32_t &x){ x = (x + 31u)  & ~31u; };
        auto align512 = [](uint32_t &x){ x = (x + 511u) & ~511u; };

        // ---- 申请一小块 UB 只用于回读打印 ----
        AscendC::LocalTensor<uint8_t> ub_mem;
        bool ok_ub = AscendC::PopStackBuffer<uint8_t, AscendC::TPosition::VECCALC>(ub_mem);
        if (!ok_ub) { AscendC::printf("PopStackBuffer UB failed\n"); return; }

        uint32_t off_ub = 0;
        AscendC::LocalTensor<float> C_ub;
        align32(off_ub);
        C_ub.SetAddrWithOffset(ub_mem, off_ub);
        C_ub.SetSize((uint32_t)(M * N * (int)sizeof(float)));
        off_ub += C_ub.GetSize();

        // ---- 在 A2/B2/CO1 位面申请矩阵核缓冲 ----
        AscendC::TBuf<AscendC::TPosition::A2>  bufA2;
        AscendC::TBuf<AscendC::TPosition::B2>  bufB2;
        AscendC::TBuf<AscendC::TPosition::CO1> bufCO1;

        uint32_t sizeA2 = (uint32_t)(M * K * (int)sizeof(half));  align512(sizeA2);
        uint32_t sizeB2 = (uint32_t)(K * N * (int)sizeof(half));  align512(sizeB2);
        uint32_t sizeC1 = (uint32_t)(M * N * (int)sizeof(float)); align512(sizeC1);

        pipe.InitBuffer(bufA2,  sizeA2);
        pipe.InitBuffer(bufB2,  sizeB2);
        pipe.InitBuffer(bufCO1, sizeC1);

        AscendC::LocalTensor<half>  A2 = bufA2.Get<half>();
        AscendC::LocalTensor<half>  B2 = bufB2.Get<half>();
        AscendC::LocalTensor<float> C1 = bufCO1.Get<float>();
        A2.SetSize((uint32_t)(M * K * (int)sizeof(half)));
        B2.SetSize((uint32_t)(K * N * (int)sizeof(half)));
        C1.SetSize((uint32_t)(M * N * (int)sizeof(float)));

        // ---- 关键:直接在分形位面“批量填充”常数 ----
        // 常数阵在任何布局下等价于逻辑全 1,因此可避开 LoadData2D 的复杂度
        AscendC::Duplicate(A2, (half)1.0f, (uint32_t)(M * K));
        AscendC::Duplicate(B2, (half)1.0f, (uint32_t)(K * N));
        AscendC::Duplicate(C1, 0.0f,      (uint32_t)(M * N));  // 累加前清零

        // (可选)确保向量填充都已完成
        AscendC::PipeBarrier<PIPE_V>();

        // ---- 关闭 HF32(void 接口)----
        AscendC::SetHF32Mode(false);
        AscendC::SetHF32TransMode(false);

        // ---- MMAD:FP16×FP16 -> FP32 ----
        AscendC::MmadParams p{};
        p.m = (uint32_t)M;
        p.n = (uint32_t)N;
        p.k = (uint32_t)K;

        AscendC::Mmad(C1, A2, B2, p);

        // 让矩阵核计算落地
        AscendC::PipeBarrier<PIPE_V>();  // 若你环境有 PIPE_M,可再加一条 PipeBarrier<PIPE_M>();

        // ---- 回 UB 打印 ----
        AscendC::DataCopy(C_ub, C1, (uint32_t)(M * N));

        AscendC::printf("\n[MMAD ones] expect each elem = %f\n", (float)K);
        for (int i = 0; i < 4; ++i) {
            for (int j = 0; j < 4; ++j)
                AscendC::printf("%f ", C_ub.GetValue(i * N + j));
            AscendC::printf("\n");
        }
        float sum0 = 0.0f;
        for (int t = 0; t < M * N; ++t) sum0 += C_ub.GetValue(t);
        AscendC::printf("[Sanity sum] %f\n", sum0);

我要发帖子