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_p2p.h"
12 : #include <securec.h>
13 : #include <sys/socket.h>
14 : #include <sys/types.h>
15 : #include <arpa/inet.h>
16 : #include <unistd.h>
17 : #include "adapter_hal_pub.h"
18 :
19 : namespace hccl {
20 2 : TransportDeviceP2p::TransportDeviceP2p(
21 : DispatcherPub* dispatcher, const std::unique_ptr<NotifyPool>& notifyPool, MachinePara& machinePara,
22 2 : std::chrono::milliseconds timeout, const TransportDeviceP2pData& transDevP2pData)
23 2 : : TransportP2p(dispatcher, notifyPool, machinePara, timeout)
24 : {
25 2 : this->remoteInputPtr_ = transDevP2pData.inputBufferPtr;
26 2 : this->remoteOutputPtr_ = transDevP2pData.outputBufferPtr;
27 2 : this->transportAttr_ = transDevP2pData.transportAttr;
28 :
29 2 : if (!machinePara.isNewOneSide) {
30 2 : this->SetNotifyPtr(transDevP2pData);
31 : }
32 2 : }
33 :
34 2 : TransportDeviceP2p::~TransportDeviceP2p() { HCCL_DEBUG("[TransportDeviceP2p] ~TransportDeviceP2p Success!"); }
35 :
36 2 : HcclResult TransportDeviceP2p::Init()
37 : {
38 2 : HCCL_INFO(
39 : "[TransportDeviceP2p][Init] machineType=[%d], serverId=[%s], localDeviceId=[%d] remoteDeviceId=[%d], "
40 : "localRank=[%u], localUserRank=[%u], remoteRank=[%u], remoteUserRank=[%u], deviceType=[%d], "
41 : "input_ptr=[%p], output_ptr=[%p], linkAttribute=[0x%x], linkMode=[%d], notifyNum[%u]",
42 : machinePara_.machineType, machinePara_.serverId.c_str(), machinePara_.localDeviceId,
43 : machinePara_.remoteDeviceId, machinePara_.localUserrank, machinePara_.localWorldRank,
44 : machinePara_.remoteUserrank, machinePara_.remoteWorldRank, machinePara_.deviceType, machinePara_.inputMem.ptr(),
45 : machinePara_.outputMem.ptr(), machinePara_.linkAttribute, machinePara_.linkMode, machinePara_.notifyNum);
46 :
47 2 : HCCL_DEBUG(
48 : "[TransportDeviceP2p][Init] transport attr: linktype[0x%x], relationship[0x%x], "
49 : "signalRecordBuff.addr[%p], signalRecordBuff.length[%llu]",
50 : transportAttr_.linkType, transportAttr_.relationship, transportAttr_.signalRecordBuff.address,
51 : transportAttr_.signalRecordBuff.length);
52 2 : HcclUs startut = TIME_NOW();
53 :
54 2 : SetUseSdmaToSignalRecord();
55 2 : if (!machinePara_.isNewOneSide) {
56 2 : CHK_RET(ConfigUseSdmaCopyToSignalRecord());
57 2 : CHK_RET(this->SetNotify());
58 : } else {
59 : // init localHcclMemExMgr_ and remoteHcclMemExMgr_ from machinePara_.localBufMem and machinePara_.remoteBufMem
60 0 : CHK_RET(InitHcclMemExMgr(machinePara_));
61 : }
62 :
63 2 : HcclUs endut = TIME_NOW();
64 2 : HCCL_INFO("[TransportDeviceP2p][Init] take time:%lld us", DURATION_US(endut - startut));
65 :
66 2 : HCCL_USER_CRITICAL_LOG(
67 : "create hccl transport:communicator[%s], local rank[%u], remote rank[%u], "
68 : "transporttype[%s]",
69 : machinePara_.tag.c_str(), machinePara_.localUserrank, machinePara_.remoteUserrank,
70 : GetLinkTypeEnumStr(GetLinkType()).c_str());
71 :
72 2 : return HCCL_SUCCESS;
73 : }
74 :
75 0 : HcclResult TransportDeviceP2p::UpdateRemoteAddr(void* remoteIn, void* remoteOut)
76 : {
77 0 : this->remoteInputPtr_ = remoteIn;
78 0 : this->remoteOutputPtr_ = remoteOut;
79 0 : return HCCL_SUCCESS;
80 : }
81 :
82 : extern "C" {
83 : drvError_t __attribute__((weak))
84 : halResAddrMap(unsigned int devId, struct res_addr_info* res_info, unsigned long* va, unsigned int* len);
85 : };
86 :
87 2 : HcclResult TransportDeviceP2p::GetNotifyAddr(s32 deviceId, const HcclSignalInfo& signalInfo, u64& addr)
88 : {
89 2 : if (halResAddrMap == nullptr) {
90 0 : HCCL_ERROR("driver package is not support function [halResAddrMap], please update the package.");
91 0 : return HCCL_E_DRV;
92 : }
93 :
94 2 : unsigned int drvDevid = 0;
95 2 : CHK_RET(hrtDrvGetLocalDevIDByHostDevID(static_cast<uint32_t>(deviceId), &drvDevid));
96 :
97 2 : res_addr_info resInfo = {};
98 2 : resInfo.id = signalInfo.tsId;
99 2 : resInfo.target_proc_type = PROCESS_CP1;
100 2 : resInfo.res_type = RES_ADDR_TYPE_STARS_NOTIFY_RECORD;
101 2 : resInfo.res_id = static_cast<uint32_t>(signalInfo.resId);
102 2 : resInfo.flag = signalInfo.flag;
103 2 : resInfo.rudevid = signalInfo.devId;
104 2 : resInfo.rsv[0] = 0; // 0 is reserved array idx
105 2 : resInfo.rsv[1] = 0; // 1 is reserved array idx
106 :
107 2 : unsigned int len = 0;
108 2 : int ret = halResAddrMap(drvDevid, &resInfo, reinterpret_cast<uint64_t*>(&addr), &len);
109 2 : if (ret != 0 || len != transportAttr_.signalRecordBuff.length || len == 0) {
110 0 : HCCL_ERROR(
111 : "[drv api]res get addr failed, result:%d, devid:%d, resType:%d, resId:%u, tsId:%d, ruDevId:%d, "
112 : "flag:%d, addr:%p, notify len:%u",
113 : ret, drvDevid, resInfo.res_type, resInfo.res_id, resInfo.id, resInfo.rudevid, resInfo.flag, addr, len);
114 0 : return HCCL_E_DRV;
115 : }
116 2 : HCCL_DEBUG(
117 : "get notify address success, devid:%d, drvDevid:%u, resType:%d, resId:%u, tsId:%d, ruDevId:%d, flag:%d, "
118 : "addr:%p",
119 : deviceId, drvDevid, resInfo.res_type, resInfo.res_id, resInfo.id, resInfo.rudevid, resInfo.flag, addr);
120 2 : return HCCL_SUCCESS;
121 : }
122 :
123 : template <typename T>
124 2 : HcclResult TransportDeviceP2p::ModifySignalAddrToVA(s32 deviceId, std::shared_ptr<T>& notify)
125 : {
126 : HcclSignalInfo signalInfo;
127 2 : CHK_PTR_NULL(notify);
128 2 : CHK_RET(notify->GetNotifyData(signalInfo));
129 2 : CHK_RET(GetNotifyAddr(deviceId, signalInfo, signalInfo.addr));
130 2 : CHK_RET(notify->SetNotifyData(signalInfo));
131 2 : return HCCL_SUCCESS;
132 : }
133 :
134 2 : HcclResult TransportDeviceP2p::CheckRelationship(u32 relationship)
135 : {
136 2 : constexpr u32 sameChip = HCCL_TRANSPORT_RELATIONSHIP_SAME_SUPERPOD | HCCL_TRANSPORT_RELATIONSHIP_SAME_SERVER
137 : | HCCL_TRANSPORT_RELATIONSHIP_SAME_CHIP;
138 2 : constexpr u32 sameServer = HCCL_TRANSPORT_RELATIONSHIP_SAME_SUPERPOD | HCCL_TRANSPORT_RELATIONSHIP_SAME_SERVER;
139 2 : constexpr u32 sameSuperpod = HCCL_TRANSPORT_RELATIONSHIP_SAME_SUPERPOD;
140 :
141 2 : if ((relationship != sameChip) && (relationship != sameServer) && (relationship != sameSuperpod)) {
142 0 : HCCL_ERROR("[TransportDeviceP2p] relationship is not support, relationship:%d", relationship);
143 0 : return HCCL_E_INTERNAL;
144 : }
145 2 : return HCCL_SUCCESS;
146 : }
147 :
148 2 : HcclResult TransportDeviceP2p::ConfigUseSdmaCopyToSignalRecord()
149 : {
150 2 : CHK_RET(CheckRelationship(transportAttr_.relationship));
151 :
152 : // AICPU展开时,在节点间使用SDMA进行notify record操作,STARS可检出节点间链路异常,触发HCCL重执行
153 2 : if (useSdmaToSignalRecord_) {
154 1 : HCCL_DEBUG("[TransportDeviceP2p] use sdma to signal record");
155 : // NOTE: DRV只支持跨节点的 notify VA 映射,不支持节点内和本地的 notify VA 映射
156 1 : CHK_RET(ModifySignalAddrToVA(machinePara_.localDeviceId, remoteSendReadyNotify_));
157 1 : CHK_RET(ModifySignalAddrToVA(machinePara_.localDeviceId, remoteSendDoneNotify_));
158 1 : for (u32 i = 0; i < notifyNum_; i++) {
159 0 : CHK_RET(ModifySignalAddrToVA(machinePara_.localDeviceId, userRemoteNotify_[i]));
160 : }
161 1 : signalMem_ = DeviceMem::create(
162 1 : reinterpret_cast<void*>(transportAttr_.signalRecordBuff.address), transportAttr_.signalRecordBuff.length);
163 1 : CHK_SMART_PTR_NULL(signalMem_);
164 : }
165 2 : return HCCL_SUCCESS;
166 : }
167 :
168 2 : HcclResult TransportDeviceP2p::SignalRecord(
169 : std::shared_ptr<RemoteNotify>& remoteSignal, u64 remoteSignalAddr, u64 remoteSignalOffset, Stream& stream)
170 : {
171 : HcclSignalInfo notifyInfo;
172 2 : CHK_RET(remoteSignal->GetNotifyData(notifyInfo));
173 2 : if (useSdmaToSignalRecord_) {
174 : DeviceMem dstDevMem
175 1 : = DeviceMem::create(reinterpret_cast<void*>(remoteSignalAddr), transportAttr_.signalRecordBuff.length);
176 1 : CHK_SMART_PTR_NULL(dstDevMem);
177 2 : return dispatcher_->SignalRecord(
178 1 : dstDevMem, signalMem_, stream, machinePara_.remoteWorldRank, transportAttr_.linkType, notifyInfo.resId);
179 1 : } else {
180 1 : return dispatcher_->SignalRecord(
181 : remoteSignal->ptr(), stream, machinePara_.remoteWorldRank, remoteSignalOffset, INVALID_VALUE_STAGE, false,
182 2 : remoteSignalAddr, notifyInfo.resId);
183 : }
184 : }
185 : } // namespace hccl
|