Support for FabricEdge APIs

Related-To: LOCI-3377

Signed-off-by: Joshua Santosh Ranjan <joshua.santosh.ranjan@intel.com>
This commit is contained in:
Joshua Santosh Ranjan
2022-09-20 09:09:12 +00:00
committed by Compute-Runtime-Automation
parent 553e194379
commit a93edd8620
24 changed files with 1046 additions and 28 deletions

View File

@@ -247,6 +247,22 @@ zeGetDeviceProcAddrTable(
return result;
}
ZE_APIEXPORT ze_result_t ZE_APICALL
zeGetDeviceExpProcAddrTable(
ze_api_version_t version,
ze_device_exp_dditable_t *pDdiTable) {
if (nullptr == pDdiTable)
return ZE_RESULT_ERROR_INVALID_ARGUMENT;
if (ZE_MAJOR_VERSION(driver_ddiTable.version) != ZE_MAJOR_VERSION(version) ||
ZE_MINOR_VERSION(driver_ddiTable.version) > ZE_MINOR_VERSION(version))
return ZE_RESULT_ERROR_UNSUPPORTED_VERSION;
ze_result_t result = ZE_RESULT_SUCCESS;
pDdiTable->pfnGetFabricVertexExp = L0::zeDeviceGetFabricVertexExp;
driver_ddiTable.core_ddiTable.DeviceExp = *pDdiTable;
return result;
}
ZE_APIEXPORT ze_result_t ZE_APICALL
zeGetCommandQueueProcAddrTable(
ze_api_version_t version,
@@ -646,3 +662,22 @@ zeGetFabricVertexExpProcAddrTable(
driver_ddiTable.core_ddiTable.FabricVertexExp = *pDdiTable;
return result;
}
ZE_APIEXPORT ze_result_t ZE_APICALL
zeGetFabricEdgeExpProcAddrTable(
ze_api_version_t version,
ze_fabric_edge_exp_dditable_t *pDdiTable) {
if (nullptr == pDdiTable)
return ZE_RESULT_ERROR_INVALID_ARGUMENT;
if (ZE_MAJOR_VERSION(driver_ddiTable.version) != ZE_MAJOR_VERSION(version) ||
ZE_MINOR_VERSION(driver_ddiTable.version) > ZE_MINOR_VERSION(version))
return ZE_RESULT_ERROR_UNSUPPORTED_VERSION;
ze_result_t result = ZE_RESULT_SUCCESS;
pDdiTable->pfnGetExp = L0::zeFabricEdgeGetExp;
pDdiTable->pfnGetVerticesExp = L0::zeFabricEdgeGetVerticesExp;
pDdiTable->pfnGetPropertiesExp = L0::zeFabricEdgeGetPropertiesExp;
driver_ddiTable.core_ddiTable.FabricEdgeExp = *pDdiTable;
return result;
}

View File

@@ -84,6 +84,27 @@ ze_result_t zeFabricVertexGetDeviceExp(
return L0::FabricVertex::fromHandle(hVertex)->getDevice(phDevice);
}
ze_result_t zeDeviceGetFabricVertexExp(ze_device_handle_t hDevice, ze_fabric_vertex_handle_t *phVertex) {
return L0::Device::fromHandle(hDevice)->getFabricVertex(phVertex);
}
ze_result_t zeFabricEdgeGetExp(ze_fabric_vertex_handle_t hVertexA, ze_fabric_vertex_handle_t hVertexB,
uint32_t *pCount, ze_fabric_edge_handle_t *phEdges) {
return L0::FabricVertex::fromHandle(hVertexA)->edgeGet(hVertexB, pCount, phEdges);
}
ze_result_t zeFabricEdgeGetVerticesExp(ze_fabric_edge_handle_t hEdge, ze_fabric_vertex_handle_t *phVertexA,
ze_fabric_vertex_handle_t *phVertexB) {
return L0::FabricEdge::fromHandle(hEdge)->getVertices(phVertexA, phVertexB);
}
ze_result_t zeFabricEdgeGetPropertiesExp(ze_fabric_edge_handle_t hEdge,
ze_fabric_edge_exp_properties_t *pEdgeProperties) {
return L0::FabricEdge::fromHandle(hEdge)->getProperties(pEdgeProperties);
}
} // namespace L0
extern "C" {
@@ -161,4 +182,35 @@ zeFabricVertexGetDeviceExp(
return L0::zeFabricVertexGetDeviceExp(hVertex, phDevice);
}
ZE_APIEXPORT ze_result_t ZE_APICALL
zeDeviceGetFabricVertexExp(
ze_device_handle_t hDevice,
ze_fabric_vertex_handle_t *phVertex) {
return L0::zeDeviceGetFabricVertexExp(hDevice, phVertex);
}
ZE_APIEXPORT ze_result_t ZE_APICALL
zeFabricEdgeGetExp(
ze_fabric_vertex_handle_t hVertexA,
ze_fabric_vertex_handle_t hVertexB,
uint32_t *pCount,
ze_fabric_edge_handle_t *phEdges) {
return L0::zeFabricEdgeGetExp(hVertexA, hVertexB, pCount, phEdges);
}
ZE_APIEXPORT ze_result_t ZE_APICALL
zeFabricEdgeGetVerticesExp(
ze_fabric_edge_handle_t hEdge,
ze_fabric_vertex_handle_t *phVertexA,
ze_fabric_vertex_handle_t *phVertexB) {
return L0::zeFabricEdgeGetVerticesExp(hEdge, phVertexA, phVertexB);
}
ZE_APIEXPORT ze_result_t ZE_APICALL
zeFabricEdgeGetPropertiesExp(
ze_fabric_edge_handle_t hEdge,
ze_fabric_edge_exp_properties_t *pEdgeProperties) {
return L0::zeFabricEdgeGetPropertiesExp(hEdge, pEdgeProperties);
}
} // extern "C"

View File

@@ -67,4 +67,23 @@ ze_result_t zeFabricVertexGetDeviceExp(
ze_fabric_vertex_handle_t hVertex,
ze_device_handle_t *phDevice);
ze_result_t zeDeviceGetFabricVertexExp(
ze_device_handle_t hDevice,
ze_fabric_vertex_handle_t *phVertex);
ze_result_t zeFabricEdgeGetExp(
ze_fabric_vertex_handle_t hVertexA,
ze_fabric_vertex_handle_t hVertexB,
uint32_t *pCount,
ze_fabric_edge_handle_t *phEdges);
ze_result_t zeFabricEdgeGetVerticesExp(
ze_fabric_edge_handle_t hEdge,
ze_fabric_vertex_handle_t *phVertexA,
ze_fabric_vertex_handle_t *phVertexB);
ze_result_t zeFabricEdgeGetPropertiesExp(
ze_fabric_edge_handle_t hEdge,
ze_fabric_edge_exp_properties_t *pEdgeProperties);
} // namespace L0

View File

@@ -135,6 +135,7 @@ struct Device : _ze_device_handle_t {
virtual ze_result_t getCsrForLowPriority(NEO::CommandStreamReceiver **csr) = 0;
virtual NEO::GraphicsAllocation *obtainReusableAllocation(size_t requiredSize, NEO::AllocationType type) = 0;
virtual void storeReusableAllocation(NEO::GraphicsAllocation &alloc) = 0;
virtual ze_result_t getFabricVertex(ze_fabric_vertex_handle_t *phVertex) const = 0;
protected:
NEO::Device *neoDevice = nullptr;

View File

@@ -1480,4 +1480,13 @@ NEO::EngineGroupType DeviceImp::getEngineGroupTypeForOrdinal(uint32_t ordinal) c
return engineGroupType;
}
ze_result_t DeviceImp::getFabricVertex(ze_fabric_vertex_handle_t *phVertex) const {
if (fabricVertex == nullptr) {
return ZE_RESULT_EXP_ERROR_DEVICE_IS_NOT_VERTEX;
}
*phVertex = fabricVertex->toHandle();
return ZE_RESULT_SUCCESS;
}
} // namespace L0

View File

@@ -116,6 +116,7 @@ struct DeviceImp : public Device {
std::vector<Device *> subDevices;
std::unordered_map<uint32_t, bool> crossAccessEnabledDevices;
DriverHandle *driverHandle = nullptr;
FabricVertex *fabricVertex = nullptr;
CommandList *pageFaultCommandList = nullptr;
ze_pci_speed_ext_t pciMaxSpeed = {-1, -1, -1};
@@ -136,7 +137,7 @@ struct DeviceImp : public Device {
using CmdListCreateFunPtrT = L0::CommandList *(*)(uint32_t, Device *, NEO::EngineGroupType, ze_command_list_flags_t, ze_result_t &);
CmdListCreateFunPtrT getCmdListCreateFunc(const ze_command_list_desc_t *desc);
FabricVertex *fabricVertex = nullptr;
ze_result_t getFabricVertex(ze_fabric_vertex_handle_t *phVertex) const override;
ze_result_t queryDeviceLuid(ze_device_luid_ext_properties_t *deviceLuidProperties);
ze_result_t setDeviceLuid(ze_device_luid_ext_properties_t *deviceLuidProperties);

View File

@@ -165,6 +165,11 @@ DriverHandleImp::~DriverHandleImp() {
}
this->fabricVertices.clear();
for (auto &edge : this->fabricEdges) {
delete edge;
}
this->fabricEdges.clear();
if (this->svmAllocsManager) {
delete this->svmAllocsManager;
this->svmAllocsManager = nullptr;
@@ -242,10 +247,15 @@ ze_result_t DriverHandleImp::initialize(std::vector<std::unique_ptr<NEO::Device>
auto deviceImpl = static_cast<DeviceImp *>(device);
auto fabricVertex = FabricVertex::createFromDevice(device);
if (fabricVertex == nullptr) {
continue;
}
deviceImpl->setFabricVertex(fabricVertex);
this->fabricVertices.push_back(fabricVertex);
}
FabricEdge::createEdgesFromVertices(this->fabricVertices, this->fabricEdges);
return ZE_RESULT_SUCCESS;
}
@@ -650,4 +660,43 @@ ze_result_t DriverHandleImp::fabricVertexGetExp(uint32_t *pCount, ze_fabric_vert
return ZE_RESULT_SUCCESS;
}
ze_result_t DriverHandleImp::fabricEdgeGetExp(ze_fabric_vertex_handle_t hVertexA, ze_fabric_vertex_handle_t hVertexB,
uint32_t *pCount, ze_fabric_edge_handle_t *phEdges) {
FabricVertex *queryVertexA = FabricVertex::fromHandle(hVertexA);
FabricVertex *queryVertexB = FabricVertex::fromHandle(hVertexB);
uint32_t maxEdges = 0, edgeUpdateIndex = 0;
bool updateEdges = false;
if (*pCount == 0) {
maxEdges = static_cast<uint32_t>(fabricEdges.size());
} else {
maxEdges = std::min<uint32_t>(*pCount, static_cast<uint32_t>(fabricEdges.size()));
}
if (phEdges != nullptr) {
updateEdges = true;
}
for (const auto &edge : fabricEdges) {
// Fabric Connections are bi-directional
if ((edge->vertexA == queryVertexA && edge->vertexB == queryVertexB) ||
(edge->vertexA == queryVertexB && edge->vertexB == queryVertexA)) {
if (updateEdges == true) {
phEdges[edgeUpdateIndex] = edge->toHandle();
}
++edgeUpdateIndex;
}
// Stop if the edges overflow the count
if (edgeUpdateIndex >= maxEdges) {
break;
}
}
*pCount = edgeUpdateIndex;
return ZE_RESULT_SUCCESS;
}
} // namespace L0

View File

@@ -19,6 +19,7 @@
namespace L0 {
class HostPointerManager;
struct FabricVertex;
struct FabricEdge;
struct DriverHandleImp : public DriverHandle {
~DriverHandleImp() override;
@@ -78,6 +79,8 @@ struct DriverHandleImp : public DriverHandle {
NEO::GraphicsAllocation *alloc,
NEO::SvmAllocationData *allocData,
Device *device);
ze_result_t fabricEdgeGetExp(ze_fabric_vertex_handle_t hVertexA, ze_fabric_vertex_handle_t hVertexB,
uint32_t *pCount, ze_fabric_edge_handle_t *phEdges);
std::unique_ptr<HostPointerManager> hostPointerManager;
// Experimental functions
@@ -88,6 +91,7 @@ struct DriverHandleImp : public DriverHandle {
std::vector<Device *> devices;
std::vector<FabricVertex *> fabricVertices;
std::vector<FabricEdge *> fabricEdges;
// Spec extensions
const std::vector<std::pair<std::string, uint32_t>> extensionsSupported = {
{ZE_FLOAT_ATOMICS_EXT_NAME, ZE_FLOAT_ATOMICS_EXT_VERSION_CURRENT},

View File

@@ -8,6 +8,7 @@ set(L0_SRCS_FABRIC
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/fabric.h
${CMAKE_CURRENT_SOURCE_DIR}/fabric_device_interface.h
${CMAKE_CURRENT_SOURCE_DIR}/fabric_device_mdfi.cpp
${CMAKE_CURRENT_SOURCE_DIR}/fabric.cpp
)

View File

@@ -10,6 +10,7 @@
#include "shared/source/helpers/string.h"
#include "level_zero/core/source/device/device_imp.h"
#include "level_zero/core/source/driver/driver_handle_imp.h"
#include "level_zero/core/source/fabric/fabric_device_interface.h"
namespace L0 {
@@ -68,10 +69,12 @@ FabricVertex *FabricVertex::createFromDevice(Device *device) {
fabricVertex->properties.address.function = pciProperties.address.function;
}
fabricVertex->pFabricDeviceInterface = FabricDeviceInterface::createFabricDeviceInterface(*fabricVertex);
UNRECOVERABLE_IF(fabricVertex->pFabricDeviceInterface == nullptr);
fabricVertex->pFabricDeviceInterfaces[FabricDeviceInterface::Type::Iaf] = FabricDeviceInterface::createFabricDeviceInterfaceIaf(fabricVertex);
fabricVertex->pFabricDeviceInterfaces[FabricDeviceInterface::Type::Mdfi] = FabricDeviceInterface::createFabricDeviceInterfaceMdfi(fabricVertex);
fabricVertex->pFabricDeviceInterface->enumerate();
for (auto const &fabricDeviceInterface : fabricVertex->pFabricDeviceInterfaces) {
fabricDeviceInterface.second->enumerate();
}
return fabricVertex;
}
@@ -103,4 +106,46 @@ ze_result_t FabricVertex::getDevice(ze_device_handle_t *phDevice) const {
return ZE_RESULT_SUCCESS;
}
ze_result_t FabricVertex::edgeGet(ze_fabric_vertex_handle_t hVertexB,
uint32_t *pCount, ze_fabric_edge_handle_t *phEdges) {
DriverHandleImp *driverHandleImp = static_cast<L0::DriverHandleImp *>(device->getDriverHandle());
return driverHandleImp->fabricEdgeGetExp(this->toHandle(), hVertexB, pCount, phEdges);
}
FabricEdge *FabricEdge::create(FabricVertex *vertexA, FabricVertex *vertexB, ze_fabric_edge_exp_properties_t &properties) {
FabricEdge *edge = new FabricEdge();
edge->vertexA = vertexA;
edge->vertexB = vertexB;
edge->properties = properties;
return edge;
}
void FabricEdge::createEdgesFromVertices(const std::vector<FabricVertex *> &vertices, std::vector<FabricEdge *> &edges) {
// Get all vertices and sub-vertices
std::vector<FabricVertex *> allVertices = {};
for (auto &fabricVertex : vertices) {
allVertices.push_back(fabricVertex);
for (auto &fabricSubVertex : fabricVertex->subVertices) {
allVertices.push_back(fabricSubVertex);
}
}
// Get edges between all vertices
for (uint32_t vertexAIndex = 0; vertexAIndex < allVertices.size(); vertexAIndex++) {
for (uint32_t vertexBIndex = vertexAIndex + 1; vertexBIndex < allVertices.size(); vertexBIndex++) {
ze_fabric_edge_exp_properties_t edgeProperty = {};
for (auto const &fabricDeviceInterface : allVertices[vertexAIndex]->pFabricDeviceInterfaces) {
bool isConnected =
fabricDeviceInterface.second->getEdgeProperty(allVertices[vertexBIndex], edgeProperty);
if (isConnected) {
edges.push_back(create(allVertices[vertexAIndex], allVertices[vertexBIndex], edgeProperty));
}
}
}
}
}
} // namespace L0

View File

@@ -7,16 +7,19 @@
#pragma once
#include "level_zero/core/source/fabric/fabric_device_interface.h"
#include <level_zero/ze_api.h>
#include <map>
#include <memory>
#include <vector>
struct _ze_fabric_vertex_handle_t {};
struct _ze_fabric_edge_handle_t {};
namespace L0 {
struct Device;
class FabricDeviceInterface;
struct DriverHandle;
struct FabricVertex : _ze_fabric_vertex_handle_t {
@@ -28,14 +31,40 @@ struct FabricVertex : _ze_fabric_vertex_handle_t {
ze_result_t getDevice(ze_device_handle_t *phDevice) const;
static FabricVertex *fromHandle(ze_fabric_vertex_handle_t handle) { return static_cast<FabricVertex *>(handle); }
inline ze_fabric_vertex_handle_t toHandle() { return this; }
std::unique_ptr<FabricDeviceInterface> pFabricDeviceInterface;
ze_result_t edgeGet(ze_fabric_vertex_handle_t hVertexB,
uint32_t *pCount, ze_fabric_edge_handle_t *phEdges);
std::map<FabricDeviceInterface::Type, std::unique_ptr<FabricDeviceInterface>> pFabricDeviceInterfaces;
std::vector<FabricVertex *> subVertices = {};
struct Device *device = nullptr;
private:
struct Device *device = nullptr;
ze_fabric_vertex_exp_properties_t properties = {};
};
std::vector<FabricVertex *> subVertices = {};
struct FabricEdge : _ze_fabric_edge_handle_t {
public:
virtual ~FabricEdge() = default;
static void createEdgesFromVertices(const std::vector<FabricVertex *> &vertices, std::vector<FabricEdge *> &edges);
static FabricEdge *create(FabricVertex *vertexA, FabricVertex *vertexB, ze_fabric_edge_exp_properties_t &properties);
ze_result_t getProperties(ze_fabric_edge_exp_properties_t *pEdgeProperties) const {
*pEdgeProperties = properties;
return ZE_RESULT_SUCCESS;
}
ze_result_t getVertices(ze_fabric_vertex_handle_t *phVertexA,
ze_fabric_vertex_handle_t *phVertexB) {
*phVertexA = vertexA->toHandle();
*phVertexB = vertexB->toHandle();
return ZE_RESULT_SUCCESS;
}
static FabricEdge *fromHandle(ze_fabric_edge_handle_t handle) { return static_cast<FabricEdge *>(handle); }
inline ze_fabric_edge_handle_t toHandle() { return this; }
ze_fabric_edge_exp_properties_t properties = {};
FabricVertex *vertexA = nullptr;
FabricVertex *vertexB = nullptr;
};
} // namespace L0

View File

@@ -7,19 +7,41 @@
#pragma once
#include "level_zero/core/source/fabric/fabric.h"
#include <level_zero/ze_api.h>
#include <memory>
namespace L0 {
struct Device;
struct FabricVertex;
class FabricDeviceInterface {
public:
enum class Type {
Undefined,
Iaf,
Mdfi
};
virtual ~FabricDeviceInterface(){};
virtual ze_result_t enumerate() = 0;
static std::unique_ptr<FabricDeviceInterface> createFabricDeviceInterface(const FabricVertex &fabricVertex);
static std::unique_ptr<FabricDeviceInterface> createFabricDeviceInterfaceIaf(const FabricVertex *fabricVertex);
static std::unique_ptr<FabricDeviceInterface> createFabricDeviceInterfaceMdfi(const FabricVertex *fabricVertex);
virtual bool getEdgeProperty(FabricVertex *neighborVertex, ze_fabric_edge_exp_properties_t &edgeProperty) = 0;
};
class FabricDeviceMdfi : public FabricDeviceInterface {
public:
FabricDeviceMdfi(Device *device) : device(device) {}
~FabricDeviceMdfi() override = default;
ze_result_t enumerate() override {
return ZE_RESULT_SUCCESS;
}
bool getEdgeProperty(FabricVertex *neighborVertex, ze_fabric_edge_exp_properties_t &edgeProperty) override;
protected:
Device *device = nullptr;
};
} // namespace L0

View File

@@ -0,0 +1,59 @@
/*
* Copyright (C) 2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "level_zero/core/source/device/device.h"
#include "level_zero/core/source/device/device_imp.h"
#include "level_zero/core/source/fabric/fabric.h"
#include "level_zero/core/source/fabric/fabric_device_interface.h"
namespace L0 {
bool FabricDeviceMdfi::getEdgeProperty(FabricVertex *neighborVertex, ze_fabric_edge_exp_properties_t &edgeProperty) {
DeviceImp *currentDeviceImp = static_cast<DeviceImp *>(device);
DeviceImp *neighborDeviceImp = static_cast<DeviceImp *>(neighborVertex->device);
// Ignore root devices
if (!currentDeviceImp->isSubdevice || !neighborDeviceImp->isSubdevice) {
return false;
}
const uint32_t currRootDeviceIndex = device->getRootDeviceIndex();
const uint32_t neighborRootDeviceIndex = neighborVertex->device->getRootDeviceIndex();
const uint32_t currSubDeviceId = static_cast<DeviceImp *>(device)->getPhysicalSubDeviceId();
const uint32_t neighborSubDeviceId = static_cast<DeviceImp *>(neighborVertex->device)->getPhysicalSubDeviceId();
if (currRootDeviceIndex == neighborRootDeviceIndex &&
currSubDeviceId < neighborSubDeviceId) {
ze_uuid_t &uuid = edgeProperty.uuid;
std::memset(uuid.id, 0, ZE_MAX_UUID_SIZE);
// Copy current Root DeviceIndex and SubDeviceId
memcpy_s(&uuid.id[0], 4, &currRootDeviceIndex, 4);
memcpy_s(&uuid.id[4], 1, &currSubDeviceId, 1);
// Copy neighboring Root DeviceIndex and SubDeviceId
memcpy_s(&uuid.id[8], 4, &neighborRootDeviceIndex, 4);
memcpy_s(&uuid.id[12], 1, &neighborSubDeviceId, 1);
memcpy_s(edgeProperty.model, ZE_MAX_FABRIC_EDGE_MODEL_EXP_SIZE, "MDFI", 5);
edgeProperty.bandwidth = 0;
edgeProperty.bandwidthUnit = ZE_BANDWIDTH_UNIT_UNKNOWN;
edgeProperty.latency = 0;
edgeProperty.latencyUnit = ZE_LATENCY_UNIT_UNKNOWN;
edgeProperty.duplexity = ZE_FABRIC_EDGE_EXP_DUPLEXITY_FULL_DUPLEX;
return true;
}
return false;
}
std::unique_ptr<FabricDeviceInterface> FabricDeviceInterface::createFabricDeviceInterfaceMdfi(const FabricVertex *fabricVertex) {
return std::unique_ptr<FabricDeviceInterface>(new (std::nothrow) FabricDeviceMdfi(fabricVertex->device));
}
} // namespace L0

View File

@@ -45,6 +45,51 @@ ze_result_t FabricDeviceIaf::enumerate() {
return result;
}
bool FabricDeviceIaf::getEdgeProperty(FabricVertex *neighborVertex, ze_fabric_edge_exp_properties_t &edgeProperty) {
bool isConnected = false;
std::vector<ze_fabric_edge_exp_properties_t> subDeviceEdgeProperties = {};
for (auto &subDeviceIaf : subDeviceIafs) {
ze_fabric_edge_exp_properties_t subDeviceEdgeProperty = {};
bool isSubdeviceConnected = subDeviceIaf->getEdgeProperty(neighborVertex, subDeviceEdgeProperty);
if (isSubdeviceConnected) {
subDeviceEdgeProperties.push_back(subDeviceEdgeProperty);
}
}
if (subDeviceEdgeProperties.size() > 0) {
ze_uuid_t &uuid = edgeProperty.uuid;
std::memset(uuid.id, 0, ZE_MAX_UUID_SIZE);
// Copy current device fabric and attach id
memcpy_s(&uuid.id[0], 4, &subDeviceEdgeProperties[0].uuid.id[0], 4);
// Use 255 (impossible tile (attach) id to identify root device)
uuid.id[4] = 255;
// Copy neighboring device fabric id
memcpy_s(&uuid.id[8], 4, &subDeviceEdgeProperties[0].uuid.id[8], 4);
memcpy_s(&uuid.id[12], 1, &subDeviceEdgeProperties[0].uuid.id[12], 1);
uint32_t accumulatedBandwidth = 0;
for (const auto &subEdgeProperty : subDeviceEdgeProperties) {
accumulatedBandwidth += subEdgeProperty.bandwidth;
}
memcpy_s(edgeProperty.model, ZE_MAX_FABRIC_EDGE_MODEL_EXP_SIZE, "XeLink", 7);
edgeProperty.bandwidth = accumulatedBandwidth;
edgeProperty.bandwidthUnit = ZE_BANDWIDTH_UNIT_BYTES_PER_NANOSEC;
edgeProperty.latency = 0;
edgeProperty.latencyUnit = ZE_LATENCY_UNIT_UNKNOWN;
edgeProperty.duplexity = ZE_FABRIC_EDGE_EXP_DUPLEXITY_FULL_DUPLEX;
isConnected = true;
}
return isConnected;
}
FabricSubDeviceIaf::FabricSubDeviceIaf(Device *device) : device(device) {
pIafNlApi = std::make_unique<IafNlApi>();
UNRECOVERABLE_IF(nullptr == pIafNlApi);
@@ -146,26 +191,111 @@ ze_result_t FabricSubDeviceIaf::getConnection(IafPort &port, FabricPortConnectio
return ZE_RESULT_SUCCESS;
}
bool FabricSubDeviceIaf::getEdgeProperty(FabricSubDeviceIaf *pNeighbourInterface,
ze_fabric_edge_exp_properties_t &edgeProperty) {
bool isConnected = false;
uint32_t accumulatedBandwidth = 0;
for (auto &connection : connections) {
if (connection.neighbourGuid == pNeighbourInterface->guid) {
accumulatedBandwidth += connection.bandwidthInBytesPerNanoSecond;
}
}
if (accumulatedBandwidth != 0) {
ze_uuid_t &uuid = edgeProperty.uuid;
DEBUG_BREAK_IF(pNeighbourInterface->connections.size() == 0);
std::memset(uuid.id, 0, ZE_MAX_UUID_SIZE);
memcpy_s(&uuid.id[0], 4, &connections[0].currentid.fabricId, 4);
memcpy_s(&uuid.id[4], 1, &connections[0].currentid.attachId, 1);
// Considering the neighboring port is attached on a subdevice, fabricId and attachId could be used from
// any of the connection
memcpy_s(&uuid.id[8], 4, &pNeighbourInterface->connections[0].currentid.fabricId, 4);
memcpy_s(&uuid.id[12], 1, &pNeighbourInterface->connections[0].currentid.attachId, 1);
memcpy_s(edgeProperty.model, ZE_MAX_FABRIC_EDGE_MODEL_EXP_SIZE, "XeLink", 7);
edgeProperty.bandwidth = accumulatedBandwidth;
edgeProperty.bandwidthUnit = ZE_BANDWIDTH_UNIT_BYTES_PER_NANOSEC;
edgeProperty.latency = 0;
edgeProperty.latencyUnit = ZE_LATENCY_UNIT_UNKNOWN;
edgeProperty.duplexity = ZE_FABRIC_EDGE_EXP_DUPLEXITY_FULL_DUPLEX;
isConnected = true;
}
return isConnected;
}
bool FabricSubDeviceIaf::getEdgeProperty(FabricVertex *neighborVertex,
ze_fabric_edge_exp_properties_t &edgeProperty) {
ze_uuid_t &uuid = edgeProperty.uuid;
bool isConnected = false;
uint32_t accumulatedBandwidth = 0;
DeviceImp *neighborDeviceImp = static_cast<DeviceImp *>(neighborVertex->device);
// If the neighbor is a root device
if (neighborDeviceImp->isSubdevice == false) {
std::vector<ze_fabric_edge_exp_properties_t> subEdgeProperties = {};
FabricDeviceIaf *deviceIaf = static_cast<FabricDeviceIaf *>(neighborVertex->pFabricDeviceInterfaces[FabricDeviceInterface::Type::Iaf].get());
// Get the edges to the neighbors subVertices
for (auto &subDeviceIaf : deviceIaf->subDeviceIafs) {
ze_fabric_edge_exp_properties_t edgeProperty = {};
bool subDevicesConnected = getEdgeProperty(subDeviceIaf.get(), edgeProperty);
if (subDevicesConnected) {
subEdgeProperties.push_back(edgeProperty);
}
}
// Add an edge for this subVertex to the neighbor root
if (subEdgeProperties.size() > 0) {
std::memset(uuid.id, 0, ZE_MAX_UUID_SIZE);
// Copy current device fabric and attach id
memcpy_s(&uuid.id[0], 4, &subEdgeProperties[0].uuid.id[0], 4);
memcpy_s(&uuid.id[4], 1, &subEdgeProperties[0].uuid.id[4], 1);
// Copy neighboring device fabric id
memcpy_s(&uuid.id[8], 4, &subEdgeProperties[0].uuid.id[8], 4);
// Use 255 (impossible tile (attach) id to identify root device)
uuid.id[12] = 255;
for (const auto &subEdgeProperty : subEdgeProperties) {
accumulatedBandwidth += subEdgeProperty.bandwidth;
}
memcpy_s(edgeProperty.model, ZE_MAX_FABRIC_EDGE_MODEL_EXP_SIZE, "XeLink", 7);
edgeProperty.bandwidth = accumulatedBandwidth;
edgeProperty.bandwidthUnit = ZE_BANDWIDTH_UNIT_BYTES_PER_NANOSEC;
edgeProperty.latency = 0;
edgeProperty.latencyUnit = ZE_LATENCY_UNIT_UNKNOWN;
edgeProperty.duplexity = ZE_FABRIC_EDGE_EXP_DUPLEXITY_FULL_DUPLEX;
isConnected = true;
}
} else {
FabricSubDeviceIaf *pNeighbourInterface =
static_cast<FabricSubDeviceIaf *>(neighborVertex->pFabricDeviceInterfaces[FabricDeviceInterface::Type::Iaf].get());
isConnected = getEdgeProperty(pNeighbourInterface, edgeProperty);
}
return isConnected;
}
void FabricSubDeviceIaf::setIafNlApi(IafNlApi *iafNlApi) {
pIafNlApi.reset(iafNlApi);
}
std::unique_ptr<FabricDeviceInterface> FabricDeviceInterface::createFabricDeviceInterface(const FabricVertex &fabricVertex) {
std::unique_ptr<FabricDeviceInterface> FabricDeviceInterface::createFabricDeviceInterfaceIaf(const FabricVertex *fabricVertex) {
ze_fabric_vertex_exp_properties_t vertexProperties = {};
fabricVertex.getProperties(&vertexProperties);
DeviceImp *deviceImp = static_cast<DeviceImp *>(fabricVertex->device);
ze_device_handle_t hDevice = nullptr;
fabricVertex.getDevice(&hDevice);
DEBUG_BREAK_IF(hDevice == nullptr);
DeviceImp *deviceImp = static_cast<DeviceImp *>(hDevice);
Device *device = static_cast<Device *>(hDevice);
if (deviceImp->isSubdevice) {
return std::unique_ptr<FabricDeviceInterface>(new (std::nothrow) FabricSubDeviceIaf(device));
return std::unique_ptr<FabricDeviceInterface>(new (std::nothrow) FabricSubDeviceIaf(fabricVertex->device));
}
return std::unique_ptr<FabricDeviceInterface>(new (std::nothrow) FabricDeviceIaf(device));
return std::unique_ptr<FabricDeviceInterface>(new (std::nothrow) FabricDeviceIaf(fabricVertex->device));
}
} // namespace L0

View File

@@ -31,6 +31,7 @@ class FabricDeviceIaf : public FabricDeviceInterface {
FabricDeviceIaf(Device *device);
~FabricDeviceIaf() override = default;
ze_result_t enumerate() override;
bool getEdgeProperty(FabricVertex *neighborVertex, ze_fabric_edge_exp_properties_t &edgeProperty) override;
std::vector<std::unique_ptr<FabricSubDeviceIaf>> subDeviceIafs = {};
protected:
@@ -44,14 +45,16 @@ class FabricSubDeviceIaf : public FabricDeviceInterface {
~FabricSubDeviceIaf() override = default;
ze_result_t enumerate() override;
void setIafNlApi(IafNlApi *iafNlApi);
bool getEdgeProperty(FabricVertex *neighborVertex, ze_fabric_edge_exp_properties_t &edgeProperty) override;
std::vector<FabricPortConnection> connections = {};
uint64_t guid = 0ull;
protected:
bool getEdgeProperty(FabricSubDeviceIaf *pNeighbourInterface,
ze_fabric_edge_exp_properties_t &edgeProperty);
ze_result_t getConnection(IafPort &port, FabricPortConnection &connection);
std::unique_ptr<IafNlApi> pIafNlApi = nullptr;
Device *device = nullptr;
uint64_t guid = 0ull;
};
} // namespace L0
} // namespace L0

View File

@@ -11,7 +11,7 @@
namespace L0 {
std::unique_ptr<FabricDeviceInterface> FabricDeviceInterface::createFabricDeviceInterface(const FabricVertex &fabricVertex) {
std::unique_ptr<FabricDeviceInterface> FabricDeviceInterface::createFabricDeviceInterfaceIaf(const FabricVertex *fabricVertex) {
return std::unique_ptr<FabricDeviceInterface>(new (std::nothrow) FabricDeviceIafStub());
}

View File

@@ -20,6 +20,9 @@ class FabricDeviceIafStub : public FabricDeviceInterface {
ze_result_t enumerate() override {
return ZE_RESULT_SUCCESS;
}
bool getEdgeProperty(FabricVertex *neighborVertex, ze_fabric_edge_exp_properties_t &edgeProperty) override {
return false;
}
};
} // namespace L0

View File

@@ -11,7 +11,7 @@
namespace L0 {
std::unique_ptr<FabricDeviceInterface> FabricDeviceInterface::createFabricDeviceInterface(const FabricVertex &fabricVertex) {
std::unique_ptr<FabricDeviceInterface> FabricDeviceInterface::createFabricDeviceInterfaceIaf(const FabricVertex *fabricVertex) {
return std::unique_ptr<FabricDeviceInterface>(new (std::nothrow) FabricDeviceIaf());
}

View File

@@ -20,6 +20,9 @@ class FabricDeviceIaf : public FabricDeviceInterface {
ze_result_t enumerate() override {
return ZE_RESULT_SUCCESS;
}
bool getEdgeProperty(FabricVertex *neighborVertex, ze_fabric_edge_exp_properties_t &edgeProperty) {
return false;
}
};
} // namespace L0

View File

@@ -54,6 +54,7 @@ set(TEST_TARGETS
zello_world_gpu
zello_world_jitc_ocloc
zello_world_usm
zello_fabric
)
include_directories(common)

View File

@@ -0,0 +1,153 @@
/*
* Copyright (C) 2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "zello_common.h"
#include <iomanip>
bool showFabricConnectivityMatrix(ze_driver_handle_t &hDriver, bool isIncludeSubDevicesEnabled) {
std::cout << " \n -- Displaying Fabric Connectivity matrix -- \n";
bool isIncludeDevices = true;
uint32_t vertexCount = 0;
std::vector<std::pair<ze_fabric_vertex_handle_t, char>> allVertices;
SUCCESS_OR_TERMINATE(zeFabricVertexGetExp(hDriver, &vertexCount, nullptr));
std::vector<ze_fabric_vertex_handle_t> vertices(vertexCount);
SUCCESS_OR_TERMINATE(zeFabricVertexGetExp(hDriver, &vertexCount, vertices.data()));
for (auto &vertex : vertices) {
if (isIncludeDevices) {
allVertices.push_back(std::make_pair(vertex, 'R'));
}
if (isIncludeSubDevicesEnabled) {
uint32_t count = 0;
SUCCESS_OR_TERMINATE(zeFabricVertexGetSubVerticesExp(vertex, &count, nullptr));
std::vector<ze_fabric_vertex_handle_t> subVertices(count);
SUCCESS_OR_TERMINATE(zeFabricVertexGetSubVerticesExp(vertex, &count, subVertices.data()));
for (auto &subVertex : subVertices) {
allVertices.push_back(std::make_pair(subVertex, 'S'));
}
}
}
if (allVertices.size() == 0) {
std::cout << " -- No Fabric Vertices !! -- \n";
return false;
}
const uint32_t elementWidth = 15;
// Print Header
for (uint32_t i = 0; i < allVertices.size(); i++) {
std::cout << std::setw(elementWidth) << "[" << allVertices[i].second << "]" << allVertices[i].first;
}
std::cout << "\n";
for (uint32_t vertexAIndex = 0; vertexAIndex < allVertices.size(); vertexAIndex++) {
std::cout << "[" << allVertices[vertexAIndex].second << "]" << allVertices[vertexAIndex].first;
for (uint32_t vertexBIndex = 0; vertexBIndex < allVertices.size(); vertexBIndex++) {
if (vertexAIndex == vertexBIndex) {
std::cout << std::setw(elementWidth) << "X";
continue;
}
uint32_t edgeCount = 0;
SUCCESS_OR_TERMINATE(zeFabricEdgeGetExp(allVertices[vertexAIndex].first, allVertices[vertexBIndex].first, &edgeCount, nullptr));
std::cout << std::setw(elementWidth) << edgeCount;
}
std::cout << "\n";
}
return true;
}
bool showFabricConnectivityProperties(ze_driver_handle_t &hDriver) {
std::cout << " \n -- Displaying Fabric Connectivity Properties -- \n";
uint32_t vertexCount = 0;
std::vector<std::pair<ze_fabric_vertex_handle_t, char>> allVertices;
SUCCESS_OR_TERMINATE(zeFabricVertexGetExp(hDriver, &vertexCount, nullptr));
std::vector<ze_fabric_vertex_handle_t> vertices(vertexCount);
SUCCESS_OR_TERMINATE(zeFabricVertexGetExp(hDriver, &vertexCount, vertices.data()));
for (auto &vertex : vertices) {
allVertices.push_back(std::make_pair(vertex, 'R'));
uint32_t count = 0;
SUCCESS_OR_TERMINATE(zeFabricVertexGetSubVerticesExp(vertex, &count, nullptr));
std::vector<ze_fabric_vertex_handle_t> subVertices(count);
SUCCESS_OR_TERMINATE(zeFabricVertexGetSubVerticesExp(vertex, &count, subVertices.data()));
for (auto &subVertex : subVertices) {
allVertices.push_back(std::make_pair(subVertex, 'S'));
}
}
if (allVertices.size() == 0) {
std::cout << " -- No Fabric Vertices !! -- \n";
return false;
}
// Print the Sub Vertices and Vertices
for (uint32_t i = 0; i < allVertices.size(); i++) {
if (allVertices[i].second == 'S') {
std::cout << "\t" << allVertices[i].first << "\n";
} else {
std::cout << allVertices[i].first << "\n";
}
}
// Show properties of all edges
for (uint32_t vertexAIndex = 0; vertexAIndex < allVertices.size(); vertexAIndex++) {
for (uint32_t vertexBIndex = vertexAIndex + 1; vertexBIndex < allVertices.size(); vertexBIndex++) {
uint32_t edgeCount = 0;
SUCCESS_OR_TERMINATE(zeFabricEdgeGetExp(allVertices[vertexAIndex].first, allVertices[vertexBIndex].first, &edgeCount, nullptr));
std::vector<ze_fabric_edge_handle_t> edges(edgeCount);
SUCCESS_OR_TERMINATE(zeFabricEdgeGetExp(allVertices[vertexAIndex].first, allVertices[vertexBIndex].first, &edgeCount, edges.data()));
if (edgeCount == 0) {
continue;
}
std::cout << "Edge A: " << allVertices[vertexAIndex].first << " -- B: " << allVertices[vertexBIndex].first << "\n";
for (auto &edge : edges) {
ze_fabric_edge_exp_properties_t edgeProperties = {};
SUCCESS_OR_TERMINATE(zeFabricEdgeGetPropertiesExp(edge, &edgeProperties));
std::cout << "Uuid: ";
for (uint32_t i = 0; i < ZE_MAX_UUID_SIZE; i++) {
std::cout << static_cast<uint32_t>(edgeProperties.uuid.id[i]) << " ";
}
std::cout << "\n";
std::cout << "Model : " << edgeProperties.model << "\n";
std::cout << "Bandwidth : " << edgeProperties.bandwidth << " | units: " << static_cast<uint32_t>(edgeProperties.bandwidthUnit) << "\n";
std::cout << "Latency : " << edgeProperties.latency << " | units: " << static_cast<uint32_t>(edgeProperties.latencyUnit) << "\n";
std::cout << "Duplexity : " << static_cast<uint32_t>(edgeProperties.duplexity) << "\n";
std::cout << "\n";
}
}
std::cout << " --- \n";
}
return true;
}
int main(int argc, char *argv[]) {
const std::string blackBoxName = "Zello Fabric";
ze_context_handle_t context = nullptr;
ze_driver_handle_t driverHandle = nullptr;
auto devices = zelloInitContextAndGetDevices(context, driverHandle);
const bool isSubDeviceDisplayEnabled = isParamEnabled(argc, argv, "-s", "--subDeviceEnable");
bool status = true;
status &= showFabricConnectivityMatrix(driverHandle, isSubDeviceDisplayEnabled);
status &= showFabricConnectivityProperties(driverHandle);
printResult(false, status, blackBoxName);
return (status ? 0 : 1);
}

View File

@@ -82,6 +82,7 @@ struct Mock<Device> : public Device {
ADDMETHOD_NOBASE_VOIDRETURN(removeDebugSession, ());
ADDMETHOD_NOBASE(obtainReusableAllocation, NEO::GraphicsAllocation *, nullptr, (size_t requiredSize, NEO::AllocationType type))
ADDMETHOD_NOBASE_VOIDRETURN(storeReusableAllocation, (NEO::GraphicsAllocation & alloc));
ADDMETHOD_CONST_NOBASE(getFabricVertex, ze_result_t, ZE_RESULT_SUCCESS, (ze_fabric_vertex_handle_t * phVertex));
DebugSession *createDebugSession(const zet_debug_config_t &config, ze_result_t &result, bool isRootAttach) override {
result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;

View File

@@ -5,9 +5,13 @@
*
*/
#include "shared/source/os_interface/device_factory.h"
#include "shared/test/common/helpers/debug_manager_state_restore.h"
#include "shared/test/common/libult/linux/drm_mock.h"
#include "shared/test/common/mocks/ult_device_factory.h"
#include "shared/test/common/test_macros/test.h"
#include "level_zero/core/source/fabric/fabric.h"
#include "level_zero/core/source/fabric/linux/fabric_device_iaf.h"
#include "level_zero/core/test/unit_tests/fixtures/device_fixture.h"
@@ -227,5 +231,269 @@ TEST_F(TestFabricIaf, GivenIafFabricAvailableWhenGetPortsReturnsErrorThenReturnE
delete subDeviceFabric;
}
using FabricIafEdgeFixture = Test<MultiDeviceFixture>;
TEST_F(FabricIafEdgeFixture, GivenMultipleDevicesAndSubDevicesWhenCreatingEdgesThenEdgesCreatedAreCorrect) {
// IAF port connection configuration
// Device | SubDevice | Port -- Connected to -- Device | SubDevice | Port
// 0 0 1 1 0 2
// 0 0 5 1 0 4
// 0 1 1 1 1 8
// 0 1 2 1 1 7
//
// Guids:
// Device 0, subdevice 0 = 0xA
// Device 0, subdevice 1 = 0xAB
// Device 1, subdevice 0 = 0xABC
// Device 1, subdevice 1 = 0xABCD
std::vector<FabricPortConnection> connection00To10;
{
FabricPortConnection connection;
connection.currentid = IafPortId(0, 0, 1);
connection.neighbourPortNumber = 2;
connection.neighbourGuid = 0xABC;
connection.bandwidthInBytesPerNanoSecond = 1;
connection.isDuplex = true;
connection00To10.push_back(connection);
}
{
FabricPortConnection connection;
connection.currentid = IafPortId(0, 0, 5);
connection.neighbourPortNumber = 4;
connection.neighbourGuid = 0xABC;
connection.bandwidthInBytesPerNanoSecond = 1;
connection.isDuplex = true;
connection00To10.push_back(connection);
}
std::vector<FabricPortConnection> connection01To11;
{
FabricPortConnection connection;
connection.currentid = IafPortId(0, 1, 1);
connection.neighbourPortNumber = 8;
connection.neighbourGuid = 0xABCD;
connection.bandwidthInBytesPerNanoSecond = 1;
connection.isDuplex = true;
connection01To11.push_back(connection);
}
{
FabricPortConnection connection;
connection.currentid = IafPortId(0, 1, 2);
connection.neighbourPortNumber = 7;
connection.neighbourGuid = 0xABCD;
connection.bandwidthInBytesPerNanoSecond = 1;
connection.isDuplex = true;
connection01To11.push_back(connection);
}
std::vector<FabricPortConnection> connection10To00;
{
FabricPortConnection connection;
connection.currentid = IafPortId(1, 0, 2);
connection.neighbourPortNumber = 1;
connection.neighbourGuid = 0xA;
connection.bandwidthInBytesPerNanoSecond = 1;
connection.isDuplex = true;
connection10To00.push_back(connection);
}
{
FabricPortConnection connection;
connection.currentid = IafPortId(1, 0, 4);
connection.neighbourPortNumber = 5;
connection.neighbourGuid = 0xA;
connection.bandwidthInBytesPerNanoSecond = 1;
connection.isDuplex = true;
connection10To00.push_back(connection);
}
std::vector<FabricPortConnection> connection11To01;
{
FabricPortConnection connection;
connection.currentid = IafPortId(1, 1, 8);
connection.neighbourPortNumber = 1;
connection.neighbourGuid = 0xAB;
connection.bandwidthInBytesPerNanoSecond = 1;
connection.isDuplex = true;
connection11To01.push_back(connection);
}
{
FabricPortConnection connection;
connection.currentid = IafPortId(1, 1, 7);
connection.neighbourPortNumber = 2;
connection.neighbourGuid = 0xAB;
connection.bandwidthInBytesPerNanoSecond = 1;
connection.isDuplex = true;
connection11To01.push_back(connection);
}
auto &fabricVertex0 = driverHandle->fabricVertices[0];
{
auto fabricDeviceIaf = static_cast<FabricDeviceIaf *>(fabricVertex0->pFabricDeviceInterfaces[FabricDeviceInterface::Type::Iaf].get());
auto &fabricSubDeviceIaf0 = fabricDeviceIaf->subDeviceIafs[0];
fabricSubDeviceIaf0->connections.clear();
fabricSubDeviceIaf0->connections = connection00To10;
fabricSubDeviceIaf0->guid = 0xA;
auto &fabricSubDeviceIaf1 = fabricDeviceIaf->subDeviceIafs[1];
fabricSubDeviceIaf1->connections.clear();
fabricSubDeviceIaf1->connections = connection01To11;
fabricSubDeviceIaf1->guid = 0xAB;
//SubVertices
auto &fabricVertex00 = fabricVertex0->subVertices[0];
auto fabricSubDeviceIaf00 = static_cast<FabricSubDeviceIaf *>(fabricVertex00->pFabricDeviceInterfaces[FabricDeviceInterface::Type::Iaf].get());
fabricSubDeviceIaf00->connections.clear();
fabricSubDeviceIaf00->connections = connection00To10;
fabricSubDeviceIaf00->guid = 0xA;
auto &fabricVertex01 = fabricVertex0->subVertices[1];
auto fabricSubDeviceIaf01 = static_cast<FabricSubDeviceIaf *>(fabricVertex01->pFabricDeviceInterfaces[FabricDeviceInterface::Type::Iaf].get());
fabricSubDeviceIaf01->connections.clear();
fabricSubDeviceIaf01->connections = connection01To11;
fabricSubDeviceIaf01->guid = 0xAB;
}
auto fabricVertex1 = static_cast<FabricVertex *>(driverHandle->fabricVertices[1]);
{
auto fabricDeviceIaf = static_cast<FabricDeviceIaf *>(fabricVertex1->pFabricDeviceInterfaces[FabricDeviceInterface::Type::Iaf].get());
auto &fabricSubDeviceIaf0 = fabricDeviceIaf->subDeviceIafs[0];
fabricSubDeviceIaf0->connections.clear();
fabricSubDeviceIaf0->connections = connection10To00;
fabricSubDeviceIaf0->guid = 0xABC;
auto &fabricSubDeviceIaf1 = fabricDeviceIaf->subDeviceIafs[1];
fabricSubDeviceIaf1->connections.clear();
fabricSubDeviceIaf1->connections = connection11To01;
fabricSubDeviceIaf1->guid = 0xABCD;
//SubVertices
auto &fabricVertex00 = fabricVertex1->subVertices[0];
auto fabricSubDeviceIaf00 = static_cast<FabricSubDeviceIaf *>(fabricVertex00->pFabricDeviceInterfaces[FabricDeviceInterface::Type::Iaf].get());
fabricSubDeviceIaf00->connections.clear();
fabricSubDeviceIaf00->connections = connection10To00;
fabricSubDeviceIaf00->guid = 0xABC;
auto &fabricVertex01 = fabricVertex1->subVertices[1];
auto fabricSubDeviceIaf01 = static_cast<FabricSubDeviceIaf *>(fabricVertex01->pFabricDeviceInterfaces[FabricDeviceInterface::Type::Iaf].get());
fabricSubDeviceIaf01->connections.clear();
fabricSubDeviceIaf01->connections = connection11To01;
fabricSubDeviceIaf01->guid = 0xABCD;
}
for (auto &edge : driverHandle->fabricEdges) {
delete edge;
}
driverHandle->fabricEdges.clear();
FabricEdge::createEdgesFromVertices(driverHandle->fabricVertices, driverHandle->fabricEdges);
constexpr uint32_t root2root = 1;
constexpr uint32_t subDevice2root = 4; // 2 root to 2 sub-devices each
constexpr uint32_t subDevice2SubDevice = 4 + 2; //4 MDFI (considering 4 roots with 2 sub-devices); 2 sub-device to sub-device XeLink
EXPECT_EQ(static_cast<uint32_t>(driverHandle->fabricEdges.size()), root2root + subDevice2root + subDevice2SubDevice);
uint32_t count = 0;
std::vector<ze_fabric_edge_handle_t> edges(30);
// Root to Root Connection
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetExp(fabricVertex1->toHandle(), fabricVertex0->toHandle(), &count, nullptr));
EXPECT_EQ(count, 1u);
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetExp(fabricVertex1->toHandle(), fabricVertex0->toHandle(), &count, edges.data()));
ze_fabric_vertex_handle_t vertexA = nullptr, vertexB = nullptr;
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetVerticesExp(edges[0], &vertexA, &vertexB));
EXPECT_EQ(vertexA, fabricVertex0);
EXPECT_EQ(vertexB, fabricVertex1);
ze_fabric_edge_exp_properties_t edgeProperties = {};
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetPropertiesExp(edges[0], &edgeProperties));
EXPECT_EQ(edgeProperties.bandwidth, 4u);
EXPECT_EQ(edgeProperties.bandwidthUnit, ZE_BANDWIDTH_UNIT_BYTES_PER_NANOSEC);
EXPECT_EQ(edgeProperties.latency, 0u);
EXPECT_EQ(edgeProperties.latencyUnit, ZE_LATENCY_UNIT_UNKNOWN);
EXPECT_EQ(strcmp(edgeProperties.model, "XeLink"), 0);
EXPECT_EQ(edgeProperties.duplexity, ZE_FABRIC_EDGE_EXP_DUPLEXITY_FULL_DUPLEX);
// Root to Sub-Devices Connection
count = 0;
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetExp(fabricVertex0->toHandle(), fabricVertex1->subVertices[0], &count, nullptr));
EXPECT_EQ(count, 1u);
edges.clear();
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetExp(fabricVertex0->toHandle(), fabricVertex1->subVertices[0], &count, edges.data()));
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetPropertiesExp(edges[0], &edgeProperties));
EXPECT_EQ(edgeProperties.bandwidth, 2u);
EXPECT_EQ(strcmp(edgeProperties.model, "XeLink"), 0);
count = 0;
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetExp(fabricVertex0->toHandle(), fabricVertex1->subVertices[1], &count, nullptr));
EXPECT_EQ(count, 1u);
edges.clear();
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetExp(fabricVertex0->toHandle(), fabricVertex1->subVertices[1], &count, edges.data()));
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetPropertiesExp(edges[0], &edgeProperties));
EXPECT_EQ(edgeProperties.bandwidth, 2u);
EXPECT_EQ(strcmp(edgeProperties.model, "XeLink"), 0);
// Sub-Devices to Root Connection
count = 0;
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetExp(fabricVertex0->subVertices[0], fabricVertex1->toHandle(), &count, nullptr));
EXPECT_EQ(count, 1u);
edges.clear();
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetExp(fabricVertex0->subVertices[0], fabricVertex1->toHandle(), &count, edges.data()));
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetPropertiesExp(edges[0], &edgeProperties));
EXPECT_EQ(edgeProperties.bandwidth, 2u);
EXPECT_EQ(strcmp(edgeProperties.model, "XeLink"), 0);
count = 0;
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetExp(fabricVertex0->subVertices[1], fabricVertex1->toHandle(), &count, nullptr));
EXPECT_EQ(count, 1u);
edges.clear();
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetExp(fabricVertex0->subVertices[1], fabricVertex1->toHandle(), &count, edges.data()));
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetPropertiesExp(edges[0], &edgeProperties));
EXPECT_EQ(edgeProperties.bandwidth, 2u);
EXPECT_EQ(strcmp(edgeProperties.model, "XeLink"), 0);
// Sub-Devices to Sub-Devices Connection
count = 0;
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetExp(fabricVertex0->subVertices[0], fabricVertex0->subVertices[1], &count, nullptr));
EXPECT_EQ(count, 1u);
edges.clear();
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetExp(fabricVertex0->subVertices[0], fabricVertex0->subVertices[1], &count, edges.data()));
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetPropertiesExp(edges[0], &edgeProperties));
EXPECT_EQ(edgeProperties.bandwidth, 0u);
EXPECT_EQ(edgeProperties.bandwidthUnit, ZE_BANDWIDTH_UNIT_UNKNOWN);
EXPECT_EQ(edgeProperties.latency, 0u);
EXPECT_EQ(edgeProperties.latencyUnit, ZE_LATENCY_UNIT_UNKNOWN);
EXPECT_EQ(strcmp(edgeProperties.model, "MDFI"), 0);
EXPECT_EQ(edgeProperties.duplexity, ZE_FABRIC_EDGE_EXP_DUPLEXITY_FULL_DUPLEX);
count = 0;
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetExp(fabricVertex1->subVertices[0], fabricVertex1->subVertices[1], &count, nullptr));
EXPECT_EQ(count, 1u);
edges.clear();
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetExp(fabricVertex1->subVertices[0], fabricVertex1->subVertices[1], &count, edges.data()));
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetPropertiesExp(edges[0], &edgeProperties));
EXPECT_EQ(strcmp(edgeProperties.model, "MDFI"), 0);
count = 0;
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetExp(fabricVertex1->subVertices[0], fabricVertex0->subVertices[0], &count, nullptr));
EXPECT_EQ(count, 1u);
edges.clear();
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetExp(fabricVertex1->subVertices[0], fabricVertex0->subVertices[0], &count, edges.data()));
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetPropertiesExp(edges[0], &edgeProperties));
EXPECT_EQ(edgeProperties.bandwidth, 2u);
EXPECT_EQ(strcmp(edgeProperties.model, "XeLink"), 0);
count = 0;
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetExp(fabricVertex1->subVertices[1], fabricVertex0->subVertices[1], &count, nullptr));
EXPECT_EQ(count, 1u);
edges.clear();
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetExp(fabricVertex1->subVertices[1], fabricVertex0->subVertices[1], &count, edges.data()));
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetPropertiesExp(edges[0], &edgeProperties));
EXPECT_EQ(edgeProperties.bandwidth, 2u);
EXPECT_EQ(strcmp(edgeProperties.model, "XeLink"), 0);
}
} // namespace ult
} // namespace L0

View File

@@ -11,11 +11,29 @@
#include "shared/test/common/test_macros/test.h"
#include "level_zero/core/source/fabric/fabric.h"
#include "level_zero/core/source/fabric/fabric_device_interface.h"
#include "level_zero/core/test/unit_tests/fixtures/device_fixture.h"
namespace L0 {
class FabricDeviceMdfi;
namespace ult {
class MockFabricDeviceInterface {
ze_result_t enumerate() { return ZE_RESULT_SUCCESS; }
bool getEdgeProperty(FabricVertex *neighborVertex, ze_fabric_edge_exp_properties_t &edgeProperty) {
if (mockEdgeProperties.size() > mockEdgePropertiesCounter) {
edgeProperty = mockEdgeProperties[mockEdgePropertiesCounter];
}
return getEdgePropertyResult;
}
std::vector<ze_fabric_edge_exp_properties_t> mockEdgeProperties = {};
uint32_t mockEdgePropertiesCounter = 0;
bool getEdgePropertyResult = true;
};
using FabricVertexFixture = Test<MultiDeviceFixture>;
TEST_F(FabricVertexFixture, WhenDevicesAreCreatedThenVerifyFabricVerticesAreCreated) {
@@ -159,5 +177,117 @@ TEST(FabricEngineInstanceTest, GivenEngineInstancedDeviceWhenFabricVerticesAreCr
EXPECT_EQ(count, 0u);
}
TEST_F(FabricVertexFixture, GivenDevicesAreCreatedWhenZeDeviceGetFabricVertexExpIsCalledThenExpectValidVertices) {
for (auto l0Device : driverHandle->devices) {
ze_fabric_vertex_handle_t hVertex = nullptr;
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeDeviceGetFabricVertexExp(l0Device->toHandle(), &hVertex));
EXPECT_NE(hVertex, nullptr);
auto deviceImp = static_cast<L0::DeviceImp *>(l0Device);
for (auto l0SubDevice : deviceImp->subDevices) {
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeDeviceGetFabricVertexExp(l0SubDevice->toHandle(), &hVertex));
EXPECT_NE(hVertex, nullptr);
}
}
}
TEST_F(FabricVertexFixture, GivenDevicesAreCreatedWhenFabricVertexIsNotSetToDeviceThenZeDeviceGetFabricVertexExpReturnsError) {
auto l0Device = driverHandle->devices[0];
auto deviceImp = static_cast<L0::DeviceImp *>(l0Device);
deviceImp->setFabricVertex(nullptr);
ze_fabric_vertex_handle_t hVertex = nullptr;
EXPECT_EQ(ZE_RESULT_EXP_ERROR_DEVICE_IS_NOT_VERTEX, L0::zeDeviceGetFabricVertexExp(l0Device->toHandle(), &hVertex));
EXPECT_EQ(hVertex, nullptr);
}
using FabricEdgeFixture = Test<MultiDeviceFixture>;
TEST_F(FabricEdgeFixture, GivenFabricVerticesAreCreatedWhenZeFabricEdgeGetExpIsCalledThenReturnSuccess) {
// Delete existing fabric edges
for (auto edge : driverHandle->fabricEdges) {
delete edge;
}
driverHandle->fabricEdges.clear();
ze_fabric_edge_exp_properties_t dummyProperties = {};
driverHandle->fabricEdges.push_back(FabricEdge::create(driverHandle->fabricVertices[0], driverHandle->fabricVertices[1], dummyProperties));
driverHandle->fabricEdges.push_back(FabricEdge::create(driverHandle->fabricVertices[0], driverHandle->fabricVertices[1], dummyProperties));
driverHandle->fabricEdges.push_back(FabricEdge::create(driverHandle->fabricVertices[0], driverHandle->fabricVertices[1], dummyProperties));
std::vector<ze_fabric_edge_handle_t> edgeHandles(10);
uint32_t count = 0;
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetExp(driverHandle->fabricVertices[0]->toHandle(),
driverHandle->fabricVertices[1]->toHandle(),
&count,
edgeHandles.data()));
EXPECT_EQ(count, 3u);
count = 2;
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetExp(driverHandle->fabricVertices[1]->toHandle(),
driverHandle->fabricVertices[0]->toHandle(),
&count,
edgeHandles.data()));
}
TEST_F(FabricEdgeFixture, GivenFabricEdgesAreCreatedWhenZeFabricEdgeGetVerticesExpIsCalledThenReturnCorrectVertices) {
// Delete existing fabric edges
for (auto edge : driverHandle->fabricEdges) {
delete edge;
}
driverHandle->fabricEdges.clear();
ze_fabric_edge_exp_properties_t dummyProperties = {};
driverHandle->fabricEdges.push_back(FabricEdge::create(driverHandle->fabricVertices[0], driverHandle->fabricVertices[1], dummyProperties));
std::vector<ze_fabric_edge_handle_t> edgeHandles(10);
uint32_t count = 1;
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetExp(driverHandle->fabricVertices[1]->toHandle(),
driverHandle->fabricVertices[0]->toHandle(),
&count,
edgeHandles.data()));
ze_fabric_vertex_handle_t hVertexA = nullptr;
ze_fabric_vertex_handle_t hVertexB = nullptr;
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetVerticesExp(edgeHandles[0], &hVertexA, &hVertexB));
EXPECT_EQ(hVertexA, driverHandle->fabricVertices[0]);
EXPECT_EQ(hVertexB, driverHandle->fabricVertices[1]);
}
TEST_F(FabricEdgeFixture, GivenFabricEdgesAreCreatedWhenZeFabricEdgeGetPropertiesExpIsCalledThenReturnCorrectProperties) {
// Delete existing fabric edges
for (auto edge : driverHandle->fabricEdges) {
delete edge;
}
driverHandle->fabricEdges.clear();
ze_fabric_edge_exp_properties_t properties = {};
properties.bandwidth = 10;
properties.latency = 20;
driverHandle->fabricEdges.push_back(FabricEdge::create(driverHandle->fabricVertices[0], driverHandle->fabricVertices[1], properties));
std::vector<ze_fabric_edge_handle_t> edgeHandles(10);
uint32_t count = 1;
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetExp(driverHandle->fabricVertices[1]->toHandle(),
driverHandle->fabricVertices[0]->toHandle(),
&count,
edgeHandles.data()));
ze_fabric_edge_exp_properties_t getProperties = {};
EXPECT_EQ(ZE_RESULT_SUCCESS, L0::zeFabricEdgeGetPropertiesExp(edgeHandles[0], &getProperties));
EXPECT_EQ(getProperties.bandwidth, 10u);
EXPECT_EQ(getProperties.latency, 20u);
}
TEST_F(FabricEdgeFixture, GivenMdfiLinksAreAvailableWhenEdgesAreCreatedThenVerifyThatBiDirectionalEdgesAreNotCreated) {
auto &fabricSubVertex1 = driverHandle->fabricVertices[0]->subVertices[1];
auto fabricDeviceMdfi = static_cast<FabricDeviceMdfi *>(fabricSubVertex1->pFabricDeviceInterfaces[FabricDeviceInterface::Type::Mdfi].get());
ze_fabric_edge_exp_properties_t unusedProperty = {};
EXPECT_FALSE(fabricDeviceMdfi->getEdgeProperty(driverHandle->fabricVertices[0]->subVertices[0], unusedProperty));
}
} // namespace ult
} // namespace L0
} // namespace L0