* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
#include "gtest/gtest.h"
#include "sim_world.h"
#include "hccl.h"
#include "hccl/hccl_types.h"
#include "acl/acl_rt.h"
#include "hccl_verifier.h"
#include "check_utils.h"
#include <thread>
#include "alg_env_config.h"
constexpr uint32_t DATATYPE_SIZE_TABLE[HCCL_DATA_TYPE_RESERVED] = {sizeof(int8_t),
sizeof(int16_t),
sizeof(int32_t),
2,
sizeof(float),
sizeof(int64_t),
sizeof(uint64_t),
sizeof(uint8_t),
sizeof(uint16_t),
sizeof(uint32_t),
8,
2,
16,
2,
1,
1,
1,
1};
using namespace HcclSim;
using namespace ops_hccl;
class DPU_SEND_RECV_TEST : public ::testing::Test {
protected:
void SetUp() override
{
ResetAlgEnvConfigInitState();
}
void TearDown() override
{
unsetenv("HCCL_OP_EXPANSION_MODE");
unsetenv("ENABLE_HOSTDPU_FOR_LLT");
unsetenv("HCCL_INDEPENDENT_OP");
unsetenv("HCCL_ENABLE_OPEN_AICPU");
}
static void SetUpTestCase()
{}
static void TearDownTestCase()
{}
};
using RankId = uint32_t;
void DPUSendRecvTest(
TopoMeta &topoMeta, const std::map<RankId, RankId> &sendRecvMap, u32 dataCount, HcclDataType dataType)
{
u32 rankSize = 0;
for (const auto &superPod : topoMeta)
for (const auto &server : superPod)
rankSize += server.size();
SimWorld::Global()->Init(topoMeta, DevType::DEV_TYPE_950);
setenv("HCCL_OP_EXPANSION_MODE", "AI_CPU", 1);
setenv("ENABLE_HOSTDPU_FOR_LLT", "1", 1);
setenv("HCCL_INDEPENDENT_OP", "1", 1);
std::vector<std::thread> threads;
for (const auto &kv : sendRecvMap) {
RankId srcRankId = kv.first;
RankId dstRankId = kv.second;
threads.emplace_back([=]() {
aclrtSetDevice(srcRankId);
aclrtStream stream = nullptr;
aclrtCreateStream(&stream);
HcclComm comm = nullptr;
CHK_RET(HcclCommInitClusterInfo("./ranktable.json", srcRankId, &comm));
u64 bufSize = dataCount * DATATYPE_SIZE_TABLE[dataType];
void *sendBuf = nullptr;
aclrtMalloc(&sendBuf, bufSize, static_cast<aclrtMemMallocPolicy>(BUFFER_INPUT_MARK));
CHK_RET(HcclSend(sendBuf, dataCount, dataType, dstRankId, comm, stream));
CHK_RET(HcclCommDestroy(comm));
return HCCL_SUCCESS;
});
threads.emplace_back([=]() {
aclrtSetDevice(dstRankId);
aclrtStream stream = nullptr;
aclrtCreateStream(&stream);
HcclComm comm = nullptr;
CHK_RET(HcclCommInitClusterInfo("./ranktable.json", dstRankId, &comm));
u64 bufSize = dataCount * DATATYPE_SIZE_TABLE[dataType];
void *recvBuf = nullptr;
aclrtMalloc(&recvBuf, bufSize, static_cast<aclrtMemMallocPolicy>(BUFFER_OUTPUT_MARK));
CHK_RET(HcclRecv(recvBuf, dataCount, dataType, srcRankId, comm, stream));
CHK_RET(HcclCommDestroy(comm));
return HCCL_SUCCESS;
});
}
for (auto &thread : threads) {
thread.join();
}
auto taskQueues = SimTaskQueue::Global()->GetAllRankTaskQueues();
for (const auto &kv : sendRecvMap) {
RankId srcRankId = kv.first;
RankId dstRankId = kv.second;
HcclResult sendRes = CheckSend(taskQueues, rankSize, dataType, dataCount, srcRankId, dstRankId);
EXPECT_TRUE(sendRes == HCCL_SUCCESS);
HcclResult recvRes = CheckRecv(taskQueues, rankSize, dataType, dataCount, srcRankId, dstRankId);
EXPECT_TRUE(recvRes == HCCL_SUCCESS);
}
SimWorld::Global()->Deinit();
};
TEST_F(DPU_SEND_RECV_TEST, dpu_send_recv_test_int32)
{
std::cout << "here 1" << endl;
TopoMeta topoMeta{{{0, 1}, {2, 3}, {4, 5}, {6, 7}}};
std::map<RankId, RankId> sendRecvMap = {{0, 1}, {2, 5}, {3, 4}, {6, 7}};
auto dataCount = 600 * 1024 * 1024;
auto dataType = HcclDataType::HCCL_DATA_TYPE_INT32;
std::cout << "func:" << endl;
DPUSendRecvTest(topoMeta, sendRecvMap, dataCount, dataType);
}
TEST_F(DPU_SEND_RECV_TEST, dpu_send_recv_test_int16)
{
TopoMeta topoMeta{{{0, 1}, {2, 3}}};
std::map<RankId, RankId> sendRecvMap = {{0, 2}, {1, 3}};
auto dataCount = 100;
auto dataType = HcclDataType::HCCL_DATA_TYPE_INT16;
DPUSendRecvTest(topoMeta, sendRecvMap, dataCount, dataType);
}
TEST_F(DPU_SEND_RECV_TEST, dpu_send_recv_test_count1)
{
TopoMeta topoMeta{{{0, 1}, {2, 3}}};
std::map<RankId, RankId> sendRecvMap = {{0, 2}, {1, 3}};
auto dataCount = 1;
auto dataType = HcclDataType::HCCL_DATA_TYPE_FP16;
DPUSendRecvTest(topoMeta, sendRecvMap, dataCount, dataType);
}
TEST_F(DPU_SEND_RECV_TEST, dpu_send_recv_test_uint16)
{
TopoMeta topoMeta{{{0}, {1}}};
std::map<RankId, RankId> sendRecvMap = {{0, 1}};
auto dataCount = 100;
auto dataType = HcclDataType::HCCL_DATA_TYPE_UINT16;
DPUSendRecvTest(topoMeta, sendRecvMap, dataCount, dataType);
}
TEST_F(DPU_SEND_RECV_TEST, dpu_send_recv_test_uint8)
{
TopoMeta topoMeta{{{0, 1, 2}, {3, 4, 5}}};
std::map<RankId, RankId> sendRecvMap = {{0, 5}, {3, 1}, {2, 4}};
auto dataCount = 256 * 1024 * 1024;
auto dataType = HcclDataType::HCCL_DATA_TYPE_UINT8;
DPUSendRecvTest(topoMeta, sendRecvMap, dataCount, dataType);
}
TEST_F(DPU_SEND_RECV_TEST, dpu_send_recv_test_fp8e5m2)
{
TopoMeta topoMeta{{{0, 1, 2, 3}, {4, 5, 6, 7}}};
std::map<RankId, RankId> sendRecvMap = {{0, 4}, {1, 6}, {2, 3}, {5, 7}};
auto dataCount = 600 * 1024 * 1024;
auto dataType = HcclDataType::HCCL_DATA_TYPE_FP8E5M2;
DPUSendRecvTest(topoMeta, sendRecvMap, dataCount, dataType);
}
TEST_F(DPU_SEND_RECV_TEST, dpu_send_recv_test_fp8e8m0)
{
TopoMeta topoMeta{{{0, 1, 2, 3}, {4, 5, 6, 7}}};
std::map<RankId, RankId> sendRecvMap = {{0, 4}, {6, 1}, {2, 3}, {5, 7}};
auto dataCount = 256 * 1024 * 1024;
auto dataType = HcclDataType::HCCL_DATA_TYPE_FP8E8M0;
DPUSendRecvTest(topoMeta, sendRecvMap, dataCount, dataType);
}
TEST_F(DPU_SEND_RECV_TEST, dpu_send_recv_test_bfp16)
{
TopoMeta topoMeta{{{0, 1, 2, 3}, {4, 5, 6, 7}}};
std::map<RankId, RankId> sendRecvMap = {{0, 4}, {6, 1}, {2, 3}, {5, 7}};
auto dataCount = 256 * 1024 * 1024;
auto dataType = HcclDataType::HCCL_DATA_TYPE_BFP16;
DPUSendRecvTest(topoMeta, sendRecvMap, dataCount, dataType);
}
TEST_F(DPU_SEND_RECV_TEST, dpu_send_recv_test_fp16)
{
TopoMeta topoMeta{{{0, 1, 2, 3}, {4, 5, 6, 7}}};
std::map<RankId, RankId> sendRecvMap = {{0, 4}, {6, 1}, {2, 3}, {5, 7}};
auto dataCount = 256 * 1024 * 1024;
auto dataType = HcclDataType::HCCL_DATA_TYPE_FP16;
DPUSendRecvTest(topoMeta, sendRecvMap, dataCount, dataType);
}
TEST_F(DPU_SEND_RECV_TEST, dpu_send_recv_test_fp32)
{
TopoMeta topoMeta{{{0, 1, 2, 3}, {4, 5, 6, 7}}};
std::map<RankId, RankId> sendRecvMap = {{0, 4}, {6, 1}, {2, 3}, {5, 7}};
auto dataCount = 256 * 1024 * 1024;
auto dataType = HcclDataType::HCCL_DATA_TYPE_FP32;
DPUSendRecvTest(topoMeta, sendRecvMap, dataCount, dataType);
}
TEST_F(DPU_SEND_RECV_TEST, dpu_send_recv_test_hif8)
{
TopoMeta topoMeta{{{0, 1, 2, 3}, {4, 5, 6, 7}}};
std::map<RankId, RankId> sendRecvMap = {{0, 4}, {6, 1}, {2, 3}, {5, 7}};
auto dataCount = 256 * 1024 * 1024;
auto dataType = HcclDataType::HCCL_DATA_TYPE_HIF8;
DPUSendRecvTest(topoMeta, sendRecvMap, dataCount, dataType);
}
TEST_F(DPU_SEND_RECV_TEST, dpu_send_recv_test_fp8e4m3)
{
TopoMeta topoMeta{{{0, 1, 2, 3}, {4, 5, 6, 7}}};
std::map<RankId, RankId> sendRecvMap = {{0, 4}, {6, 1}, {2, 3}, {5, 7}};
auto dataCount = 256 * 1024 * 1024;
auto dataType = HcclDataType::HCCL_DATA_TYPE_FP8E4M3;
DPUSendRecvTest(topoMeta, sendRecvMap, dataCount, dataType);
}
TEST_F(DPU_SEND_RECV_TEST, dpu_send_recv_test_int8)
{
TopoMeta topoMeta{{{0, 1, 2, 3}, {4, 5, 6, 7}}};
std::map<RankId, RankId> sendRecvMap = {{0, 4}, {6, 1}, {2, 3}, {5, 7}};
auto dataCount = 256 * 1024 * 1024;
auto dataType = HcclDataType::HCCL_DATA_TYPE_INT8;
DPUSendRecvTest(topoMeta, sendRecvMap, dataCount, dataType);
}
TEST_F(DPU_SEND_RECV_TEST, dpu_send_recv_test_fp64)
{
TopoMeta topoMeta{{{0, 1, 2, 3}, {4, 5, 6, 7}}};
std::map<RankId, RankId> sendRecvMap = {{0, 4}, {6, 1}, {2, 3}, {5, 7}};
auto dataCount = 256 * 1024 * 1024;
auto dataType = HcclDataType::HCCL_DATA_TYPE_FP64;
DPUSendRecvTest(topoMeta, sendRecvMap, dataCount, dataType);
}