Skip to content

Commit 76675fa

Browse files
authored
Linux device discovery for TRT-RTX Ep (microsoft#26210)
### Description <!-- Describe your changes. --> This change adds PCIe bus_id to the properties detected during Linux device discovery. This property is used to enable device discovery on Linux for the TRT-RTX execution provider. ### Motivation and Context <!-- - Why is this change required? What problem does it solve? --> I want to use device discovery for TRT-EP also on Linux. This changes have already been tested with the newly added inference samples microsoft/onnxruntime-inference-examples#529 . @gedoensmax for visibilty
1 parent 05b3d81 commit 76675fa

6 files changed

Lines changed: 55 additions & 10 deletions

File tree

onnxruntime/core/platform/linux/device_discovery.cc

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <fstream>
88
#include <iterator>
99
#include <optional>
10+
#include <regex>
1011
#include <string_view>
1112

1213
#include "core/common/common.h"
@@ -114,6 +115,28 @@ std::optional<bool> IsGpuDiscrete(uint16_t vendor_id, uint16_t device_id) {
114115
return std::nullopt;
115116
}
116117

118+
Status GetPciBusId(const std::filesystem::path& sysfs_path, std::optional<std::string>& pci_bus_id) {
119+
constexpr const char* regex_pattern{R"([0-9a-f]+:[0-9a-f]+:[0-9a-f]+[.][0-9a-f]+)"};
120+
static const std::regex pci_bus_id_regex(regex_pattern);
121+
122+
std::error_code error_code;
123+
auto pci_bus_id_path = std::filesystem::canonical(sysfs_path / "device", error_code); // resolves symlink to PCI bus id, e.g. 0000:65:00.0
124+
ORT_RETURN_IF_ERROR(ErrorCodeToStatus(error_code));
125+
126+
auto pci_bus_id_filename = pci_bus_id_path.filename();
127+
if (std::regex_match(pci_bus_id_filename.string(), pci_bus_id_regex)) {
128+
pci_bus_id = pci_bus_id_filename.string();
129+
} else {
130+
pci_bus_id = {};
131+
LOGS_DEFAULT(WARNING) << MakeString("Skipping pci_bus_id for PCI path at \"",
132+
pci_bus_id_path.string(),
133+
"\" because filename \"", pci_bus_id_filename, "\" dit not match expected pattern of ",
134+
regex_pattern);
135+
};
136+
137+
return Status::OK();
138+
}
139+
117140
Status GetGpuDeviceFromSysfs(const GpuSysfsPathInfo& path_info, OrtHardwareDevice& gpu_device_out) {
118141
OrtHardwareDevice gpu_device{};
119142
const auto& sysfs_path = path_info.path;
@@ -140,6 +163,12 @@ Status GetGpuDeviceFromSysfs(const GpuSysfsPathInfo& path_info, OrtHardwareDevic
140163
gpu_device.metadata.Add("Discrete", (*is_gpu_discrete ? "1" : "0"));
141164
}
142165

166+
std::optional<std::string> pci_bus_id;
167+
ORT_RETURN_IF_ERROR(GetPciBusId(sysfs_path, pci_bus_id));
168+
if (pci_bus_id) {
169+
gpu_device.metadata.Add("pci_bus_id", std::move(*pci_bus_id));
170+
}
171+
143172
gpu_device.type = OrtHardwareDeviceType_GPU;
144173

145174
gpu_device_out = std::move(gpu_device);

onnxruntime/core/providers/nv_tensorrt_rtx/nv_provider_factory.cc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,7 @@ struct NvTensorRtRtxEpFactory : OrtEpFactory {
584584
* @return True if the device is a supported NVIDIA GPU, false otherwise.
585585
*/
586586
bool IsOrtHardwareDeviceSupported(const OrtHardwareDevice& device) {
587+
#if _WIN32
587588
const auto& metadata_entries = device.metadata.Entries();
588589
const auto it = metadata_entries.find("LUID");
589590
if (it == metadata_entries.end()) {
@@ -625,6 +626,25 @@ struct NvTensorRtRtxEpFactory : OrtEpFactory {
625626
}
626627

627628
return false;
629+
#else
630+
const auto& metadata_entries = device.metadata.Entries();
631+
const auto it = metadata_entries.find("pci_bus_id");
632+
if (it == metadata_entries.end()) {
633+
return false;
634+
}
635+
auto& target_id = it->second;
636+
int cuda_device_idx = 0;
637+
if (cudaDeviceGetByPCIBusId(&cuda_device_idx, target_id.c_str()) != cudaSuccess) {
638+
return false;
639+
}
640+
641+
cudaDeviceProp prop;
642+
if (cudaGetDeviceProperties(&prop, cuda_device_idx) != cudaSuccess) {
643+
return false;
644+
}
645+
// Ampere architecture or newer is required.
646+
return prop.major >= 8;
647+
#endif
628648
}
629649

630650
// Creates and returns OrtEpDevice instances for all OrtHardwareDevices that this factory supports.

onnxruntime/core/providers/nv_tensorrt_rtx/version_script.lds

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
VERS_1.0 {
33
global:
44
GetProvider;
5+
CreateEpFactories;
6+
ReleaseEpFactory;
57

68
# Hide everything else.
79
local:

onnxruntime/test/providers/nv_tensorrt_rtx/nv_basic_test.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,6 @@ INSTANTIATE_TEST_SUITE_P(NvExecutionProviderTest, TypeTests,
278278
),
279279
[](const testing::TestParamInfo<TypeTests::ParamType>& info) { return getTypeAsName(info.param); });
280280

281-
#ifdef _WIN32
282281
static bool SessionHasEp(Ort::Session& session, const char* ep_name) {
283282
// Access the underlying InferenceSession.
284283
const OrtSession* ort_session = session;
@@ -295,7 +294,6 @@ static bool SessionHasEp(Ort::Session& session, const char* ep_name) {
295294
}
296295

297296
// Tests autoEP feature to automatically select an EP that supports the GPU.
298-
// Currently only works on Windows.
299297
TEST(NvExecutionProviderTest, AutoEp_PreferGpu) {
300298
PathString model_name = ORT_TSTR("nv_execution_provider_auto_ep.onnx");
301299
std::string graph_name = "test";
@@ -305,7 +303,11 @@ TEST(NvExecutionProviderTest, AutoEp_PreferGpu) {
305303
CreateBaseModel(model_name, graph_name, dims);
306304

307305
{
306+
#if _WIN32
308307
ort_env->RegisterExecutionProviderLibrary(kNvTensorRTRTXExecutionProvider, ORT_TSTR("onnxruntime_providers_nv_tensorrt_rtx.dll"));
308+
#else
309+
ort_env->RegisterExecutionProviderLibrary(kNvTensorRTRTXExecutionProvider, ORT_TSTR("libonnxruntime_providers_nv_tensorrt_rtx.so"));
310+
#endif
309311

310312
Ort::SessionOptions so;
311313
so.SetEpSelectionPolicy(OrtExecutionProviderDevicePolicy_PREFER_GPU);
@@ -602,7 +604,5 @@ TEST(NvExecutionProviderTest, FP4CustomOpModel) {
602604
LOGS_DEFAULT(INFO) << "[NvExecutionProviderTest] TRT FP4 dynamic quantize model run completed successfully";
603605
}
604606

605-
#endif
606-
607607
} // namespace test
608608
} // namespace onnxruntime

onnxruntime/test/providers/nv_tensorrt_rtx/nv_ep_context_test.cc

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ namespace test {
1414

1515
RegisteredEpDeviceUniquePtr AppendTrtEtxEP(Ort::SessionOptions& session_options, std::unordered_map<std::string, std::string>& option_map) {
1616
RegisteredEpDeviceUniquePtr nv_tensorrt_rtx_ep;
17-
#ifdef _WIN32
1817
/// Since this test runs after other tests that use registration interface this test has to use it as well
1918
/// windows as otherwise the kernel registry inside the EP will not be populated. The legacy APis ony call the initialize once.
2019
Utils::RegisterAndGetNvTensorRtRtxEp(*ort_env, nv_tensorrt_rtx_ep);
@@ -26,9 +25,6 @@ RegisteredEpDeviceUniquePtr AppendTrtEtxEP(Ort::SessionOptions& session_options,
2625
}
2726
}
2827
session_options.AppendExecutionProvider_V2(*ort_env, {selected_device}, option_map);
29-
#else
30-
session_options.AppendExecutionProvider(onnxruntime::kNvTensorRTRTXExecutionProvider, option_map);
31-
#endif
3228
return nv_tensorrt_rtx_ep;
3329
}
3430

onnxruntime/test/providers/nv_tensorrt_rtx/test_nv_trt_rtx_ep_util.cc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424

2525
namespace onnxruntime {
2626
namespace test {
27-
#ifdef _WIN32
2827

2928
Utils::NvTensorRtRtxEpInfo Utils::nv_tensorrt_rtx_ep_info;
3029

@@ -61,7 +60,6 @@ void Utils::RegisterAndGetNvTensorRtRtxEp(Ort::Env& env, RegisteredEpDeviceUniqu
6160
c_api.UnregisterExecutionProviderLibrary(env, nv_tensorrt_rtx_ep_info.registration_name.c_str());
6261
});
6362
}
64-
#endif // _WIN32
6563

6664
void CreateBaseModel(const PathString& model_name,
6765
std::string graph_name,

0 commit comments

Comments
 (0)