LCOV - code coverage report
Current view: top level - legacy/ascend910/platform/resource/transport/onesided/device - transport_device_roce_mem.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 175 0
Test Date: 2026-08-18 17:47:01 Functions: 0.0 % 24 0

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2025 Huawei Technologies Co., Ltd.
       3              :  * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
       4              :  * CANN Open Software License Agreement Version 2.0 (the "License").
       5              :  * Please refer to the License for details. You may not use this file except in compliance with the License.
       6              :  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
       7              :  * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
       8              :  * See LICENSE in the root of the software repository for the full text of the License.
       9              :  */
      10              : 
      11              : #include "transport_device_roce_mem.h"
      12              : #include "log.h"
      13              : #include "dispatcher_pub.h"
      14              : #include "adapter_verbs.h"
      15              : 
      16              : namespace hccl {
      17              : std::atomic<u64> TransportDeviceRoceMem::wrIdOffset_;
      18              : 
      19            0 : TransportDeviceRoceMem::TransportDeviceRoceMem(
      20              :     const std::unique_ptr<NotifyPool>& notifyPool, const HcclNetDevCtx& netDevCtx, const HcclDispatcher& dispatcher,
      21            0 :     AttrInfo& attrInfo, bool aicpuUnfoldMode, const HcclQpInfoV2& qpInfo)
      22              :     : TransportMem(notifyPool, netDevCtx, dispatcher, attrInfo, aicpuUnfoldMode),
      23            0 :       timeout_{std::chrono::microseconds((attrInfo.timeout == INVALID_UINT) ? 0 : attrInfo.timeout)},
      24            0 :       qpInfo_{qpInfo}
      25            0 : {}
      26              : 
      27            0 : TransportDeviceRoceMem::~TransportDeviceRoceMem() {}
      28              : 
      29            0 : HcclResult TransportDeviceRoceMem::ExchangeMemDesc(
      30              :     [[maybe_unused]] const RmaMemDescs& localMemDescs, [[maybe_unused]] RmaMemDescs& remoteMemDescs,
      31              :     [[maybe_unused]] u32& actualNumOfRemote)
      32              : {
      33            0 :     HCCL_ERROR("TransportDeviceRoceMem doesn't support ExchangeMemDesc");
      34            0 :     return HCCL_E_NOT_SUPPORT;
      35              : }
      36              : 
      37            0 : HcclResult TransportDeviceRoceMem::EnableMemAccess(
      38              :     [[maybe_unused]] const RmaMemDesc& remoteMemDesc, [[maybe_unused]] RmaMem& remoteMem)
      39              : {
      40            0 :     HCCL_ERROR("TransportDeviceRoceMem doesn't support EnableMemAccess");
      41            0 :     return HCCL_E_NOT_SUPPORT;
      42              : }
      43              : 
      44            0 : HcclResult TransportDeviceRoceMem::DisableMemAccess([[maybe_unused]] const RmaMemDesc& remoteMemDesc)
      45              : {
      46            0 :     HCCL_ERROR("TransportDeviceRoceMem doesn't support DisableMemAccess");
      47            0 :     return HCCL_E_NOT_SUPPORT;
      48              : }
      49              : 
      50            0 : HcclResult TransportDeviceRoceMem::SetSocket([[maybe_unused]] const std::shared_ptr<HcclSocket>& socket)
      51              : {
      52            0 :     HCCL_ERROR("TransportDeviceRoceMem doesn't support SetSocket");
      53            0 :     return HCCL_E_NOT_SUPPORT;
      54              : }
      55              : 
      56            0 : HcclResult TransportDeviceRoceMem::Connect([[maybe_unused]] s32 timeoutSec)
      57              : {
      58            0 :     HCCL_ERROR("TransportDeviceRoceMem doesn't support Connect");
      59            0 :     return HCCL_E_NOT_SUPPORT;
      60              : }
      61              : 
      62            0 : HcclResult TransportDeviceRoceMem::Write(
      63              :     [[maybe_unused]] const HcclBuf& remoteMem, [[maybe_unused]] const HcclBuf& localMem,
      64              :     [[maybe_unused]] const rtStream_t& stream)
      65              : {
      66            0 :     HCCL_ERROR("TransportDeviceRoceMem doesn't support HcclBuf Write");
      67            0 :     return HCCL_E_NOT_SUPPORT;
      68              : }
      69              : 
      70            0 : HcclResult TransportDeviceRoceMem::Read(
      71              :     [[maybe_unused]] const HcclBuf& localMem, [[maybe_unused]] const HcclBuf& remoteMem,
      72              :     [[maybe_unused]] const rtStream_t& stream)
      73              : {
      74            0 :     HCCL_ERROR("TransportDeviceRoceMem doesn't support HcclBuf Read");
      75            0 :     return HCCL_E_NOT_SUPPORT;
      76              : }
      77              : 
      78            0 : HcclResult TransportDeviceRoceMem::Write(
      79              :     [[maybe_unused]] const RmaOpMem& remoteMem, [[maybe_unused]] const RmaOpMem& localMem,
      80              :     [[maybe_unused]] const rtStream_t& stream)
      81              : {
      82            0 :     HCCL_ERROR("TransportDeviceRoceMem doesn't support RmaOpMem Write");
      83            0 :     return HCCL_E_NOT_SUPPORT;
      84              : }
      85              : 
      86            0 : HcclResult TransportDeviceRoceMem::Read(
      87              :     [[maybe_unused]] const RmaOpMem& localMem, [[maybe_unused]] const RmaOpMem& remoteMem,
      88              :     [[maybe_unused]] const rtStream_t& stream)
      89              : {
      90            0 :     HCCL_ERROR("TransportDeviceRoceMem doesn't support RmaOpMem Read");
      91            0 :     return HCCL_E_NOT_SUPPORT;
      92              : }
      93              : 
      94            0 : HcclResult TransportDeviceRoceMem::AddOpFence([[maybe_unused]] const rtStream_t& stream)
      95              : {
      96            0 :     HCCL_ERROR("TransportDeviceRoceMem doesn't support HOST AddOpFence");
      97            0 :     return HCCL_E_NOT_SUPPORT;
      98              : }
      99              : 
     100            0 : HcclResult TransportDeviceRoceMem::GetTransInfo(
     101              :     [[maybe_unused]] HcclQpInfoV2& qpInfo, [[maybe_unused]] u32* lkey, [[maybe_unused]] u32* rkey,
     102              :     [[maybe_unused]] HcclBuf* localMem, [[maybe_unused]] HcclBuf* remoteMem, [[maybe_unused]] u32 num)
     103              : {
     104            0 :     HCCL_ERROR("TransportDeviceRoceMem doesn't support GetTransInfo");
     105            0 :     return HCCL_E_NOT_SUPPORT;
     106              : }
     107              : 
     108            0 : HcclResult TransportDeviceRoceMem::WaitOpFence([[maybe_unused]] const rtStream_t& stream)
     109              : {
     110            0 :     HCCL_ERROR("TransportDeviceRoceMem doesn't support WaitOpFence");
     111            0 :     return HCCL_E_NOT_SUPPORT;
     112              : }
     113              : 
     114            0 : HcclResult TransportDeviceRoceMem::TransportDeviceRoceMem::BatchWrite(
     115              :     const std::vector<MemDetails>& remoteMems, const std::vector<MemDetails>& localMems, Stream& stream)
     116              : {
     117            0 :     return BatchOp(stream, localMems, remoteMems, false, false);
     118              : }
     119              : 
     120            0 : HcclResult TransportDeviceRoceMem::BatchRead(
     121              :     const std::vector<MemDetails>& localMems, const std::vector<MemDetails>& remoteMems, Stream& stream)
     122              : {
     123            0 :     return BatchOp(stream, localMems, remoteMems, true, false);
     124              : }
     125              : 
     126              : HcclResult
     127            0 : TransportDeviceRoceMem::AddOpFence(const MemDetails& localFenceMem, const MemDetails& remoteFenceMem, Stream& stream)
     128              : {
     129            0 :     std::vector<MemDetails> localMems(1, localFenceMem);
     130            0 :     std::vector<MemDetails> remoteMems(1, remoteFenceMem);
     131            0 :     return BatchOp(stream, localMems, remoteMems, true, true);
     132            0 : }
     133              : 
     134            0 : HcclResult TransportDeviceRoceMem::DoorBellSend(Stream& stream, u64 dbInfo, u32 wrDataLen, bool fence)
     135              : {
     136            0 :     HCCL_DEBUG("[DoorBellSend] dbIndex[%#x] dbInfo[%#llx] remoteRankId[%u]", qpInfo_.dbIndex, dbInfo, remoteRankId_);
     137            0 :     RdmaTaskInfo rdmaInfo;
     138            0 :     WrInformation wrInfo;
     139            0 :     wrInfo.notifyId = 0;
     140            0 :     wrInfo.wrData.memList.len = wrDataLen;
     141            0 :     rdmaInfo.wrInfos.emplace_back(wrInfo);
     142            0 :     rdmaInfo.rdmaType = fence ? RdmaType::RDMA_SEND_NOTIFY : RdmaType::RDMA_SEND_PAYLOAD;
     143            0 :     rdmaInfo.remoteRank = remoteRankId_;
     144            0 :     HcclResult ret = HCCL_SUCCESS;
     145            0 :     DispatcherPub* dispatcher = static_cast<DispatcherPub*>(dispatcher_);
     146            0 :     ret = dispatcher->RdmaSend(qpInfo_.dbIndex, dbInfo, stream, rdmaInfo);
     147            0 :     CHK_PRT_RET(
     148              :         ret != HCCL_SUCCESS,
     149              :         HCCL_ERROR(
     150              :             "[DoorBellSend] RdmaSend failed, ret[%u]. dbIndex[%#x] dbInfo[%#llx] remoteRankId[%u]", ret,
     151              :             qpInfo_.dbIndex, dbInfo, rdmaInfo.remoteRank),
     152              :         ret);
     153            0 :     std::vector<Stream> subStreams;
     154            0 :     ret = dispatcher->LaunchTasksEx(stream, subStreams);
     155            0 :     CHK_PRT_RET(
     156              :         ret != HCCL_SUCCESS,
     157              :         HCCL_ERROR(
     158              :             "[DoorBellSend] LaunchTask failed, ret[%u]. dbIndex[%#x] dbInfo[%#llx] remoteRankId[%u]", ret,
     159              :             qpInfo_.dbIndex, dbInfo, rdmaInfo.remoteRank),
     160              :         ret);
     161            0 :     return HCCL_SUCCESS;
     162            0 : }
     163              : 
     164            0 : HcclResult TransportDeviceRoceMem::FillMemDetails(
     165              :     std::vector<MemDetails>& localMemList, std::vector<MemDetails>& remoteMemList, MemDetails& localMem,
     166              :     MemDetails& remoteMem)
     167              : {
     168            0 :     CHK_PRT_RET(
     169              :         localMem.size != remoteMem.size,
     170              :         HCCL_ERROR(
     171              :             "[TransportDeviceRoceMem][FillMemDetails] "
     172              :             "local buffer size[%llu] is not equal to remote buffer size[%llu]",
     173              :             localMem.size, remoteMem.size),
     174              :         HCCL_E_PARA);
     175            0 :     u64 remainingBytes = localMem.size;
     176            0 :     while (remainingBytes > 0) {
     177            0 :         const u64 chunkBytes = (remainingBytes > MAX_RDMA_WQE_SIZE) ? MAX_RDMA_WQE_SIZE : remainingBytes;
     178            0 :         localMem.size = chunkBytes;
     179            0 :         remoteMem.size = chunkBytes;
     180            0 :         localMemList.emplace_back(localMem);
     181            0 :         remoteMemList.emplace_back(remoteMem);
     182            0 :         localMem.addr += chunkBytes;
     183            0 :         remoteMem.addr += chunkBytes;
     184            0 :         remainingBytes -= chunkBytes;
     185              :     }
     186            0 :     return HCCL_SUCCESS;
     187              : }
     188              : 
     189            0 : HcclResult TransportDeviceRoceMem::BatchOp(
     190              :     Stream& stream, const std::vector<MemDetails>& localMems, const std::vector<MemDetails>& remoteMems, bool isRead,
     191              :     bool fence)
     192              : {
     193            0 :     constexpr u32 MAX_RDMA_WQE_NUM = 64; // related to qp depth
     194            0 :     CHK_PRT_RET(
     195              :         localMems.size() != remoteMems.size(),
     196              :         HCCL_ERROR(
     197              :             "[TransportDeviceRoceMem][BatchOp] "
     198              :             "local buffer num[%llu] is not equal to remote buffer num[%llu]",
     199              :             localMems.size(), remoteMems.size()),
     200              :         HCCL_E_PARA);
     201            0 :     u64 dbInfo = 0;
     202            0 :     u32 wqeCount = 0;
     203            0 :     u64 wrDataLen = 0;
     204            0 :     const u32 memNum = localMems.size();
     205            0 :     for (u32 index = 0; index < memNum; index++) {
     206            0 :         MemDetails localMem = localMems[index];
     207            0 :         MemDetails remoteMem = remoteMems[index];
     208            0 :         wrDataLen += localMem.size;
     209            0 :         std::vector<MemDetails> localMemList;
     210            0 :         std::vector<MemDetails> remoteMemList;
     211            0 :         CHK_RET(FillMemDetails(localMemList, remoteMemList, localMem, remoteMem));
     212            0 :         CHK_RET(BatchPostSend(stream, dbInfo, localMemList, remoteMemList, isRead, fence, wqeCount, wrDataLen));
     213            0 :         if (wqeCount >= MAX_RDMA_WQE_NUM) {
     214            0 :             CHK_RET(DoorBellSend(stream, dbInfo, wrDataLen, fence));
     215            0 :             wqeCount = 0;
     216            0 :             wrDataLen = 0;
     217              :         }
     218            0 :     }
     219            0 :     if (wqeCount != 0) {
     220            0 :         CHK_RET(DoorBellSend(stream, dbInfo, wrDataLen, fence));
     221              :     }
     222            0 :     return HCCL_SUCCESS;
     223              : }
     224              : 
     225            0 : HcclResult TransportDeviceRoceMem::BatchPostSend(
     226              :     Stream& stream, u64& dbInfo, std::vector<MemDetails>& localMemList, std::vector<MemDetails>& remoteMemList,
     227              :     bool isRead, bool fence, u32& wqeCount, u64& wrDataLen)
     228              : {
     229            0 :     const u32 wrTotalCount = localMemList.size();
     230            0 :     u32 sendWrCount = 0;
     231            0 :     while (sendWrCount < wrTotalCount) {
     232            0 :         const u32 wrCount = std::min(wrTotalCount - sendWrCount, SEND_WR_LEN);
     233            0 :         CHK_RET(PostSend(
     234              :             stream, dbInfo, &(localMemList[sendWrCount]), &(remoteMemList[sendWrCount]), wrCount, isRead, fence,
     235              :             wqeCount, wrDataLen));
     236            0 :         sendWrCount += wrCount;
     237            0 :         wqeCount += wrCount;
     238              :     }
     239            0 :     return HCCL_SUCCESS;
     240              : }
     241              : 
     242            0 : HcclResult TransportDeviceRoceMem::PostSend(
     243              :     Stream& stream, u64& dbInfo, struct MemDetails* localMems, struct MemDetails* remoteMems, u32 memNum, bool isRead,
     244              :     bool fence, u32& wqeCount, u64& wrDataLen)
     245              : {
     246            0 :     constexpr u32 RETRY_DELAY_THRESH = 100;
     247            0 :     u32 retryCount = 0;
     248            0 :     auto startTime = std::chrono::steady_clock::now();
     249            0 :     HcclResult ret = HCCL_E_NETWORK;
     250            0 :     while (ret != HCCL_SUCCESS) {
     251            0 :         RdmaOp opCode = isRead ? RdmaOp::OP_READ : RdmaOp::OP_WRITE;
     252            0 :         ret = RdmaPostSend(dbInfo, localMems, remoteMems, memNum, opCode, fence);
     253            0 :         if (ret == HCCL_E_AGAIN) {
     254            0 :             if ((retryCount == 0) && (wqeCount != 0)) {
     255            0 :                 HCCL_WARNING(
     256              :                     "[PostSend] retry with DoorBellSend, isRead[%u] remoteRankId[%u] wqeCount[%u]", isRead,
     257              :                     remoteRankId_, wqeCount);
     258            0 :                 CHK_RET(DoorBellSend(stream, dbInfo, wrDataLen, fence));
     259            0 :                 wqeCount = 0;
     260            0 :                 wrDataLen = 0;
     261            0 :             } else {
     262            0 :                 CHK_PRT_RET(
     263              :                     timeout_ == std::chrono::microseconds(0),
     264              :                     HCCL_ERROR("[PostSend] failed without retry, isRead[%u] remoteRankId[%u]", isRead, remoteRankId_),
     265              :                     ret);
     266            0 :                 auto elapsedTime = std::chrono::duration_cast<std::chrono::microseconds>(
     267            0 :                     std::chrono::steady_clock::now() - startTime);
     268            0 :                 CHK_PRT_RET(
     269              :                     elapsedTime >= timeout_,
     270              :                     HCCL_ERROR(
     271              :                         "[PostSend] failed after timeout, elapsedTime[%lld us] isRead[%u] remoteRankId[%u]",
     272              :                         elapsedTime.count(), isRead, remoteRankId_),
     273              :                     ret);
     274            0 :                 if (retryCount % RETRY_DELAY_THRESH == 0) {
     275            0 :                     HCCL_WARNING(
     276              :                         "[PostSend] retryCount[%u] after failed, elapsedTime[%lld us] isRead[%u] "
     277              :                         "remoteRankId[%u]",
     278              :                         retryCount, elapsedTime.count(), isRead, remoteRankId_);
     279              :                 }
     280            0 :                 SaluSleep(
     281            0 :                     ONE_MILLISECOND_OF_USLEEP * std::min(CeilDiv(retryCount, RETRY_DELAY_THRESH), RETRY_DELAY_THRESH));
     282              :             }
     283            0 :             ++retryCount;
     284            0 :             continue; // to retry
     285            0 :         }
     286            0 :         CHK_PRT_RET(
     287              :             ret != HCCL_SUCCESS,
     288              :             HCCL_ERROR("[PostSend] HnsPostSend failed[%u], isRead[%u] remoteRankId[%u]", ret, isRead, remoteRankId_),
     289              :             ret);
     290            0 :         if (retryCount != 0) {
     291            0 :             HCCL_INFO("[PostSend] retry success, isRead[%u] remoteRankId[%u]", isRead, remoteRankId_);
     292              :         }
     293              :     }
     294            0 :     return HCCL_SUCCESS;
     295              : }
     296              : 
     297            0 : HcclResult TransportDeviceRoceMem::RdmaPostSend(
     298              :     u64& dbInfo, MemDetails* localMems, MemDetails* remoteMems, u32 memNum, RdmaOp opCode, bool fence)
     299              : {
     300            0 :     CHK_PTR_NULL(localMems);
     301            0 :     CHK_PTR_NULL(remoteMems);
     302              : 
     303            0 :     CHK_PRT_RET(
     304              :         memNum > SEND_WR_LEN,
     305              :         HCCL_ERROR(
     306              :             "[TransportDeviceRoceMem][RdmaPostSend] buffer size is:%u over SEND_WR_LEN: %u", memNum, SEND_WR_LEN),
     307              :         HCCL_E_PARA);
     308            0 :     const u32 last = memNum - 1;
     309            0 :     struct ibv_send_wr sendWr[SEND_WR_LEN] = {};
     310            0 :     struct ibv_sge sge[SEND_WR_LEN] = {};
     311            0 :     for (u32 index = 0; index < memNum; index++) {
     312              :         // 设置WR的SGE
     313            0 :         sge[index].addr = localMems[index].addr;
     314            0 :         sge[index].length = remoteMems[index].size;
     315            0 :         sge[index].lkey = localMems[index].key;
     316              : 
     317              :         // 设置WR属性
     318            0 :         sendWr[index].wr_id = wrIdOffset_.fetch_add(1, std::memory_order_relaxed);
     319            0 :         sendWr[index].num_sge = 1; // 只有一个SGE
     320            0 :         sendWr[index].sg_list = &sge[index];
     321            0 :         sendWr[index].wr.rdma.remote_addr = remoteMems[index].addr;
     322            0 :         sendWr[index].wr.rdma.rkey = remoteMems[index].key;
     323            0 :         sendWr[index].next = (index == last) ? nullptr : &sendWr[index + 1]; // 第一个WR指向第二个WR
     324            0 :         sendWr[index].send_flags = (index == last) ?
     325              :                                        (fence ? (IBV_SEND_SIGNALED | IBV_SEND_FENCE) : IBV_SEND_SIGNALED) :
     326              :                                        0; // 最后一个WR才需要回复CQE
     327            0 :         sendWr[index].opcode = static_cast<enum ibv_wr_opcode>(opCode);
     328            0 :         HCCL_DEBUG(
     329              :             "[TransportDeviceRoceMem][RdmaPostSend] Direct ibv_post_send[%llu], opcode=[0x%x], "
     330              :             "remote_addr=[0x%llx], size=[%u], fence[%u]",
     331              :             wrIdOffset_.load(), sendWr[index].opcode, sendWr[index].wr.rdma.remote_addr, sendWr[index].sg_list->length,
     332              :             fence);
     333              :     }
     334              : 
     335            0 :     struct ibv_send_wr* badWr = nullptr;
     336            0 :     struct WrExpRsp exp_rsp = {};
     337            0 :     struct ibv_qp* qp = reinterpret_cast<struct ibv_qp*>(qpInfo_.qpPtr);
     338            0 :     CHK_PTR_NULL(qp);
     339            0 :     HCCL_DEBUG(
     340              :         "[TransportDeviceRoceMem][RdmaPostSend] qp=%p, handle=%u, qp_num=%u, qp_type=%d, qp_stat=%d", qp, qp->handle,
     341              :         qp->qp_num, qp->qp_type, qp->state);
     342            0 :     HcclResult ret = HrtHnsIbvExpPostSend(qp, &sendWr[0], &badWr, &exp_rsp);
     343            0 :     CHK_PRT_RET(
     344              :         ret != HCCL_SUCCESS && ret != HCCL_E_AGAIN,
     345              :         HCCL_ERROR(
     346              :             "[TransportDeviceRoceMem][RdmaPostSend] failed, qp=%p, handle=%u, qp_num=%u, qp_type=%d, qp_stat=%d", qp,
     347              :             qp->handle, qp->qp_num, qp->qp_type, qp->state),
     348              :         ret);
     349            0 :     if (ret == HCCL_SUCCESS) {
     350            0 :         dbInfo = exp_rsp.db_info;
     351              :     }
     352            0 :     return ret;
     353            0 : }
     354              : } // namespace hccl
        

Generated by: LCOV version 2.0-1