This is an automated email from the ASF dual-hosted git repository.
tqchen pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm-tirx.git
The following commit(s) were added to refs/heads/main by this push:
new a51a6e758 [FIX] Parse device versions as integer components (#218)
a51a6e758 is described below
commit a51a6e758983cdb044b2387735c32d9700fb9504
Author: Tianqi Chen <[email protected]>
AuthorDate: Fri Nov 6 20:32:48 2026 -0500
[FIX] Parse device versions as integer components (#218)
Parse CUDA compute capabilities and OpenCL versions as integer
major/minor components, and compare OpenCL versions lexicographically.
This avoids interpreting version strings as locale-sensitive
floating-point values.
Remove the unused ARM architecture-version parsing helpers.
---
src/backend/cuda/codegen/target_kind.cc | 8 +++--
src/backend/opencl/runtime/opencl_device_api.cc | 18 +++++-----
src/codegen/llvm/canonicalizer/arm_aprofile.cc | 19 ----------
src/support/version.h | 47 +++++++++++++++++++++++++
4 files changed, 62 insertions(+), 30 deletions(-)
diff --git a/src/backend/cuda/codegen/target_kind.cc
b/src/backend/cuda/codegen/target_kind.cc
index d0d2d9938..ec750d687 100644
--- a/src/backend/cuda/codegen/target_kind.cc
+++ b/src/backend/cuda/codegen/target_kind.cc
@@ -35,6 +35,8 @@
#include <string>
+#include "../../../support/version.h"
+
namespace tvm {
namespace backend {
@@ -83,7 +85,8 @@ ffi::Map<ffi::String, ffi::Any>
UpdateCUDAAttrs(ffi::Map<ffi::String, ffi::Any>
// Require an explicit architecture when resolving compilation, not here.
return target;
}
- archInt = std::stod(version.cast<std::string>()) * 10 + 0.1;
+ auto [major, minor] = support::ParseVersion(version.cast<std::string>());
+ archInt = major * 10 + minor;
if (archInt >= 90) {
target.Set("arch", ffi::String("sm_") + std::to_string(archInt) + "a");
} else {
@@ -106,7 +109,8 @@ ffi::Map<ffi::String, ffi::Any>
UpdateNVPTXAttrs(ffi::Map<ffi::String, ffi::Any>
LOG(WARNING) << "Unable to detect CUDA version, default to
\"-mcpu=sm_50\" instead";
arch = 50;
} else {
- arch = std::stod(version.cast<std::string>()) * 10 + 0.1;
+ auto [major, minor] = support::ParseVersion(version.cast<std::string>());
+ arch = major * 10 + minor;
}
target.Set("mcpu", ffi::String("sm_") + std::to_string(arch));
}
diff --git a/src/backend/opencl/runtime/opencl_device_api.cc
b/src/backend/opencl/runtime/opencl_device_api.cc
index 9d48a9bcd..864d7bc74 100644
--- a/src/backend/opencl/runtime/opencl_device_api.cc
+++ b/src/backend/opencl/runtime/opencl_device_api.cc
@@ -29,6 +29,7 @@
#include <sstream>
+#include "../../../support/version.h"
#include "../memory_scope.h"
#include "opencl_common.h"
@@ -799,28 +800,27 @@ void OpenCLWorkspace::Init(const std::string& type_key,
const std::string& devic
}
std::vector<cl_device_id> devices_matched =
cl::GetDeviceIDs(platform_id, device_type);
std::vector<cl_device_id> supported_devices = {};
- auto get_version_str = [](int version) {
- std::ostringstream out;
- out.precision(1);
- out << std::fixed << version / 100.f;
- return out.str();
+ constexpr std::pair<int, int> target_version = {CL_TARGET_OPENCL_VERSION
/ 100,
+ CL_TARGET_OPENCL_VERSION
% 100 / 10};
+ auto get_version_str = [](std::pair<int, int> version) {
+ return std::to_string(version.first) + "." +
std::to_string(version.second);
};
for (auto& device : devices_matched) {
std::string ver = GetOpenCLVersion(device);
- int opencl_version = std::stod(ver) * 100;
- if (opencl_version >= CL_TARGET_OPENCL_VERSION) {
+ auto opencl_version = support::ParseVersion(ver);
+ if (opencl_version >= target_version) {
supported_devices.push_back(device);
} else {
std::string dev_msg = GetDeviceInfo(device, CL_DEVICE_NAME) +
" has OpenCL version == " +
get_version_str(opencl_version);
LOG(WARNING) << "TVM supports devices with OpenCL version >= "
- << get_version_str(CL_TARGET_OPENCL_VERSION) << ",
device " << dev_msg
+ << get_version_str(target_version) << ", device " <<
dev_msg
<< ". This device will be ignored.";
if (noDevicesErrorMsg.empty()) {
noDevicesErrorMsg =
"Probably this error happen because TVM supports devices with
OpenCL version >= " +
- get_version_str(CL_TARGET_OPENCL_VERSION) + ". We found the
following devices:\n";
+ get_version_str(target_version) + ". We found the following
devices:\n";
}
noDevicesErrorMsg += "\t" + dev_msg + "\n";
}
diff --git a/src/codegen/llvm/canonicalizer/arm_aprofile.cc
b/src/codegen/llvm/canonicalizer/arm_aprofile.cc
index cf1b3d78b..efaf89f1f 100644
--- a/src/codegen/llvm/canonicalizer/arm_aprofile.cc
+++ b/src/codegen/llvm/canonicalizer/arm_aprofile.cc
@@ -38,25 +38,6 @@ namespace canonicalizer {
namespace llvm {
namespace aprofile {
-double GetArchVersion(ffi::Array<ffi::String> mattr) {
- for (const ffi::String& attr : mattr) {
- std::string attr_string = attr;
- size_t attr_len = attr_string.size();
- if (attr_len >= 4 && attr_string.substr(0, 2) == "+v" &&
attr_string.back() == 'a') {
- std::string version_string = attr_string.substr(2, attr_string.size() -
2);
- return atof(version_string.data());
- }
- }
- return 0.0;
-}
-
-double GetArchVersion(ffi::Optional<ffi::Array<ffi::String>> attr) {
- if (!attr) {
- return false;
- }
- return GetArchVersion(attr.value());
-}
-
bool IsAArch32(ffi::Optional<ffi::String> mtriple, ffi::Optional<ffi::String>
mcpu) {
if (mtriple) {
bool is_mprofile = mcpu && mcpu.value().starts_with("cortex-m");
diff --git a/src/support/version.h b/src/support/version.h
new file mode 100644
index 000000000..ecc98eaac
--- /dev/null
+++ b/src/support/version.h
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*! \file version.h
+ * \brief Integer parsing for device version strings.
+ */
+#ifndef TVM_SUPPORT_VERSION_H_
+#define TVM_SUPPORT_VERSION_H_
+
+#include <string>
+#include <utility>
+
+namespace tvm {
+namespace support {
+
+inline std::pair<int, int> ParseVersion(const std::string& version) {
+ size_t end;
+ int major = std::stoi(version, &end);
+ int minor = 0;
+ // Like numeric prefix parsing, allow an absent minor or trailing vendor
text.
+ if (end + 1 < version.size() && version[end] == '.' && version[end + 1] >=
'0' &&
+ version[end + 1] <= '9') {
+ minor = std::stoi(version.substr(end + 1));
+ }
+ return {major, minor};
+}
+
+} // namespace support
+} // namespace tvm
+
+#endif // TVM_SUPPORT_VERSION_H_