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