You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tvm.apache.org by GitBox <gi...@apache.org> on 2022/05/29 21:14:56 UTC
[GitHub] [tvm] elvin-n opened a new pull request, #11505: Fix max concurrency number in runtime for Intel processors
elvin-n opened a new pull request, #11505:
URL: https://github.com/apache/tvm/pull/11505
Add number of cores detection using cpuid instruction based on
DNNL implementation
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [tvm] areusch commented on a diff in pull request #11505: Fix max concurrency number in runtime for Intel processors
Posted by GitBox <gi...@apache.org>.
areusch commented on code in PR #11505:
URL: https://github.com/apache/tvm/pull/11505#discussion_r896107952
##########
src/runtime/threading_backend.cc:
##########
@@ -40,11 +40,158 @@
#define HEXAGON_STACK_ALIGNMENT 32
#endif
#include <algorithm>
+#include <string>
#include <thread>
#define CURRENT_THREAD_HANDLE (static_cast<std::thread::native_handle_type>(0))
namespace tvm {
namespace runtime {
namespace threading {
+#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
+#ifdef _MSC_VER
+#if (_MSC_VER < 1400)
+static inline __declspec(naked) void __cpuid(int[4], int) {
+ __asm {
+ push ebx
+ push esi
+ mov eax, dword ptr [esp + 4 * 2 + 8] // eaxIn
+ cpuid
+ mov esi, dword ptr [esp + 4 * 2 + 4] // data
+ mov dword ptr [esi], eax
+ mov dword ptr [esi + 4], ebx
+ mov dword ptr [esi + 8], ecx
+ mov dword ptr [esi + 12], edx
+ pop esi
+ pop ebx
+ ret
+ }
+}
+#else
+#include <intrin.h> // for __cpuid
+#endif
+#else
+#ifndef __GNUC_PREREQ
+#define __GNUC_PREREQ(major, minor) \
+ ((((__GNUC__) << 16) + (__GNUC_MINOR__)) >= (((major) << 16) + (minor)))
+#endif
+#if __GNUC_PREREQ(4, 3) && !defined(__APPLE__)
+#include <cpuid.h>
+#else
+// avoid err on Apple: can't find a register in class `BREG' while reloading `asm'
+#if defined(__APPLE__) && defined(_M_IX86)
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn), "2"(ecxIn))
+#else
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn), "2"(ecxIn))
+#endif
+#endif
+#endif
+
+unsigned int Cpu::get_num_cores(IntelCpuTopologyLevel level) const {
+ if (!x2apic_supported_) throw std::string("x2apic_supported_ is not supported");
+ switch (level) {
+ case SmtLevel:
+ return num_cores_[level - 1];
+ case CoreLevel:
+ return num_cores_[level - 1] / num_cores_[SmtLevel - 1];
+ default:
+ throw std::string("x2apic_supported_ is not supported");
+ }
+}
+
+/*
+ data[] = { eax, ebx, ecx, edx }
+*/
+void Cpu::get_cpuid(unsigned int eaxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuid(reinterpret_cast<int*>(data), eaxIn);
+#else
+ __cpuid(eaxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+void Cpu::get_cpuid_ex(unsigned int eaxIn, unsigned int ecxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuidex(reinterpret_cast<int*>(data), eaxIn, ecxIn);
+#else
+ __cpuid_count(eaxIn, ecxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+
+typedef uint64_t Type;
+static const Type NONE = 0;
+static const Type tINTEL = 1 << 24;
+static const Type tAMD = 1 << 25;
+
+Cpu::Cpu() : type_(NONE), x2apic_supported_(false), num_cores_() {
+ unsigned int data[4] = {};
+ const unsigned int& ECX = data[2];
+ get_cpuid(0, data);
+ static const char intel[] = "ntel";
+ static const char amd[] = "cAMD";
+ if (ECX == get32bit_ss_be(amd)) {
+ type_ |= tAMD;
+ }
+ if (ECX == get32bit_ss_be(intel)) {
+ type_ |= tINTEL;
+ }
+
+ set_num_cores();
+}
+bool Cpu::is_intel() { return type_ & tINTEL; }
+
+bool Cpu::is_amd() { return type_ & tAMD; }
+
+unsigned int Cpu::get32bit_ss_be(const char* x) const {
+ return x[0] | (x[1] << 8) | (x[2] << 16) | (x[3] << 24);
+}
+
+unsigned int Cpu::extract_bit(unsigned int val, unsigned int base, unsigned int end) {
+ return (val >> base) & ((1u << (end - base)) - 1);
+}
+
+void Cpu::set_num_cores() {
+ if ((type_ & tINTEL) == 0) return;
+
+ unsigned int data[4] = {};
+
+ /* CAUTION: These numbers are configuration as shipped by Intel. */
+ get_cpuid_ex(0x0, 0, data);
+ if (data[0] >= 0xB) {
+ /*
+ if leaf 11 exists(x2APIC is supported),
+ we use it to get the number of smt cores and cores on socket
+
+ leaf 0xB can be zeroed-out by a hypervisor
+ */
+ x2apic_supported_ = true;
+ for (unsigned int i = 0; i < max_topology_levels; i++) {
+ get_cpuid_ex(0xB, i, data);
+ IntelCpuTopologyLevel level = (IntelCpuTopologyLevel)extract_bit(data[2], 8, 15);
+ if (level == SmtLevel || level == CoreLevel) {
+ num_cores_[level - 1] = extract_bit(data[1], 0, 15);
+ }
+ }
+ /*
+ Fallback values in case a hypervisor has 0xB leaf zeroed-out.
+ */
+ num_cores_[SmtLevel - 1] = (std::max)(1u, num_cores_[SmtLevel - 1]);
Review Comment:
i agree with @tkonolige that depending on a library that's specifically meant for reading CPU info like this is better than just a piece of a library because the update story is likely to be better. however, this could be bit more effort than was intended here. @elvin-n i'll let you choose which way to address this.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [tvm] tqchen commented on a diff in pull request #11505: Fix max concurrency number in runtime for Intel processors
Posted by GitBox <gi...@apache.org>.
tqchen commented on code in PR #11505:
URL: https://github.com/apache/tvm/pull/11505#discussion_r894711056
##########
src/runtime/threading_backend.cc:
##########
@@ -40,11 +40,158 @@
#define HEXAGON_STACK_ALIGNMENT 32
#endif
#include <algorithm>
+#include <string>
#include <thread>
#define CURRENT_THREAD_HANDLE (static_cast<std::thread::native_handle_type>(0))
namespace tvm {
namespace runtime {
namespace threading {
+#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
+#ifdef _MSC_VER
+#if (_MSC_VER < 1400)
+static inline __declspec(naked) void __cpuid(int[4], int) {
+ __asm {
+ push ebx
+ push esi
+ mov eax, dword ptr [esp + 4 * 2 + 8] // eaxIn
+ cpuid
+ mov esi, dword ptr [esp + 4 * 2 + 4] // data
+ mov dword ptr [esi], eax
+ mov dword ptr [esi + 4], ebx
+ mov dword ptr [esi + 8], ecx
+ mov dword ptr [esi + 12], edx
+ pop esi
+ pop ebx
+ ret
+ }
+}
+#else
+#include <intrin.h> // for __cpuid
+#endif
+#else
+#ifndef __GNUC_PREREQ
+#define __GNUC_PREREQ(major, minor) \
+ ((((__GNUC__) << 16) + (__GNUC_MINOR__)) >= (((major) << 16) + (minor)))
+#endif
+#if __GNUC_PREREQ(4, 3) && !defined(__APPLE__)
+#include <cpuid.h>
+#else
+// avoid err on Apple: can't find a register in class `BREG' while reloading `asm'
+#if defined(__APPLE__) && defined(_M_IX86)
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn), "2"(ecxIn))
+#else
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn), "2"(ecxIn))
+#endif
+#endif
+#endif
+
+unsigned int Cpu::get_num_cores(IntelCpuTopologyLevel level) const {
+ if (!x2apic_supported_) throw std::string("x2apic_supported_ is not supported");
+ switch (level) {
+ case SmtLevel:
+ return num_cores_[level - 1];
+ case CoreLevel:
+ return num_cores_[level - 1] / num_cores_[SmtLevel - 1];
+ default:
+ throw std::string("x2apic_supported_ is not supported");
+ }
+}
+
+/*
+ data[] = { eax, ebx, ecx, edx }
+*/
+void Cpu::get_cpuid(unsigned int eaxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuid(reinterpret_cast<int*>(data), eaxIn);
+#else
+ __cpuid(eaxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+void Cpu::get_cpuid_ex(unsigned int eaxIn, unsigned int ecxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuidex(reinterpret_cast<int*>(data), eaxIn, ecxIn);
+#else
+ __cpuid_count(eaxIn, ecxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+
+typedef uint64_t Type;
+static const Type NONE = 0;
+static const Type tINTEL = 1 << 24;
+static const Type tAMD = 1 << 25;
+
+Cpu::Cpu() : type_(NONE), x2apic_supported_(false), num_cores_() {
+ unsigned int data[4] = {};
+ const unsigned int& ECX = data[2];
+ get_cpuid(0, data);
+ static const char intel[] = "ntel";
+ static const char amd[] = "cAMD";
+ if (ECX == get32bit_ss_be(amd)) {
+ type_ |= tAMD;
+ }
+ if (ECX == get32bit_ss_be(intel)) {
+ type_ |= tINTEL;
+ }
+
+ set_num_cores();
+}
+bool Cpu::is_intel() { return type_ & tINTEL; }
+
+bool Cpu::is_amd() { return type_ & tAMD; }
+
+unsigned int Cpu::get32bit_ss_be(const char* x) const {
+ return x[0] | (x[1] << 8) | (x[2] << 16) | (x[3] << 24);
+}
+
+unsigned int Cpu::extract_bit(unsigned int val, unsigned int base, unsigned int end) {
+ return (val >> base) & ((1u << (end - base)) - 1);
+}
+
+void Cpu::set_num_cores() {
+ if ((type_ & tINTEL) == 0) return;
+
+ unsigned int data[4] = {};
+
+ /* CAUTION: These numbers are configuration as shipped by Intel. */
+ get_cpuid_ex(0x0, 0, data);
+ if (data[0] >= 0xB) {
+ /*
+ if leaf 11 exists(x2APIC is supported),
+ we use it to get the number of smt cores and cores on socket
+
+ leaf 0xB can be zeroed-out by a hypervisor
+ */
+ x2apic_supported_ = true;
+ for (unsigned int i = 0; i < max_topology_levels; i++) {
+ get_cpuid_ex(0xB, i, data);
+ IntelCpuTopologyLevel level = (IntelCpuTopologyLevel)extract_bit(data[2], 8, 15);
+ if (level == SmtLevel || level == CoreLevel) {
+ num_cores_[level - 1] = extract_bit(data[1], 0, 15);
+ }
+ }
+ /*
+ Fallback values in case a hypervisor has 0xB leaf zeroed-out.
+ */
+ num_cores_[SmtLevel - 1] = (std::max)(1u, num_cores_[SmtLevel - 1]);
Review Comment:
Given there is still history which traces to the original file. it would still be good to put into 3rdparty to be extra careful as long as there is no mechanism problems. The LICENSE seems to be fine, and we can add that to https://github.com/apache/tvm/tree/main/licenses
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [tvm] tkonolige commented on a diff in pull request #11505: Fix max concurrency number in runtime for Intel processors
Posted by GitBox <gi...@apache.org>.
tkonolige commented on code in PR #11505:
URL: https://github.com/apache/tvm/pull/11505#discussion_r894865631
##########
src/runtime/threading_backend.cc:
##########
@@ -40,11 +40,158 @@
#define HEXAGON_STACK_ALIGNMENT 32
#endif
#include <algorithm>
+#include <string>
#include <thread>
#define CURRENT_THREAD_HANDLE (static_cast<std::thread::native_handle_type>(0))
namespace tvm {
namespace runtime {
namespace threading {
+#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
+#ifdef _MSC_VER
+#if (_MSC_VER < 1400)
+static inline __declspec(naked) void __cpuid(int[4], int) {
+ __asm {
+ push ebx
+ push esi
+ mov eax, dword ptr [esp + 4 * 2 + 8] // eaxIn
+ cpuid
+ mov esi, dword ptr [esp + 4 * 2 + 4] // data
+ mov dword ptr [esi], eax
+ mov dword ptr [esi + 4], ebx
+ mov dword ptr [esi + 8], ecx
+ mov dword ptr [esi + 12], edx
+ pop esi
+ pop ebx
+ ret
+ }
+}
+#else
+#include <intrin.h> // for __cpuid
+#endif
+#else
+#ifndef __GNUC_PREREQ
+#define __GNUC_PREREQ(major, minor) \
+ ((((__GNUC__) << 16) + (__GNUC_MINOR__)) >= (((major) << 16) + (minor)))
+#endif
+#if __GNUC_PREREQ(4, 3) && !defined(__APPLE__)
+#include <cpuid.h>
+#else
+// avoid err on Apple: can't find a register in class `BREG' while reloading `asm'
+#if defined(__APPLE__) && defined(_M_IX86)
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn), "2"(ecxIn))
+#else
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn), "2"(ecxIn))
+#endif
+#endif
+#endif
+
+unsigned int Cpu::get_num_cores(IntelCpuTopologyLevel level) const {
+ if (!x2apic_supported_) throw std::string("x2apic_supported_ is not supported");
+ switch (level) {
+ case SmtLevel:
+ return num_cores_[level - 1];
+ case CoreLevel:
+ return num_cores_[level - 1] / num_cores_[SmtLevel - 1];
+ default:
+ throw std::string("x2apic_supported_ is not supported");
+ }
+}
+
+/*
+ data[] = { eax, ebx, ecx, edx }
+*/
+void Cpu::get_cpuid(unsigned int eaxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuid(reinterpret_cast<int*>(data), eaxIn);
+#else
+ __cpuid(eaxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+void Cpu::get_cpuid_ex(unsigned int eaxIn, unsigned int ecxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuidex(reinterpret_cast<int*>(data), eaxIn, ecxIn);
+#else
+ __cpuid_count(eaxIn, ecxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+
+typedef uint64_t Type;
+static const Type NONE = 0;
+static const Type tINTEL = 1 << 24;
+static const Type tAMD = 1 << 25;
+
+Cpu::Cpu() : type_(NONE), x2apic_supported_(false), num_cores_() {
+ unsigned int data[4] = {};
+ const unsigned int& ECX = data[2];
+ get_cpuid(0, data);
+ static const char intel[] = "ntel";
+ static const char amd[] = "cAMD";
+ if (ECX == get32bit_ss_be(amd)) {
+ type_ |= tAMD;
+ }
+ if (ECX == get32bit_ss_be(intel)) {
+ type_ |= tINTEL;
+ }
+
+ set_num_cores();
+}
+bool Cpu::is_intel() { return type_ & tINTEL; }
+
+bool Cpu::is_amd() { return type_ & tAMD; }
+
+unsigned int Cpu::get32bit_ss_be(const char* x) const {
+ return x[0] | (x[1] << 8) | (x[2] << 16) | (x[3] << 24);
+}
+
+unsigned int Cpu::extract_bit(unsigned int val, unsigned int base, unsigned int end) {
+ return (val >> base) & ((1u << (end - base)) - 1);
+}
+
+void Cpu::set_num_cores() {
+ if ((type_ & tINTEL) == 0) return;
+
+ unsigned int data[4] = {};
+
+ /* CAUTION: These numbers are configuration as shipped by Intel. */
+ get_cpuid_ex(0x0, 0, data);
+ if (data[0] >= 0xB) {
+ /*
+ if leaf 11 exists(x2APIC is supported),
+ we use it to get the number of smt cores and cores on socket
+
+ leaf 0xB can be zeroed-out by a hypervisor
+ */
+ x2apic_supported_ = true;
+ for (unsigned int i = 0; i < max_topology_levels; i++) {
+ get_cpuid_ex(0xB, i, data);
+ IntelCpuTopologyLevel level = (IntelCpuTopologyLevel)extract_bit(data[2], 8, 15);
+ if (level == SmtLevel || level == CoreLevel) {
+ num_cores_[level - 1] = extract_bit(data[1], 0, 15);
+ }
+ }
+ /*
+ Fallback values in case a hypervisor has 0xB leaf zeroed-out.
+ */
+ num_cores_[SmtLevel - 1] = (std::max)(1u, num_cores_[SmtLevel - 1]);
Review Comment:
If we have to add a third-party dependency I would much prefer to to use PyTorch's cpuinfo instead of including all of oneDNN.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [tvm] elvin-n commented on pull request #11505: Fix max concurrency number in runtime for Intel processors
Posted by GitBox <gi...@apache.org>.
elvin-n commented on PR #11505:
URL: https://github.com/apache/tvm/pull/11505#issuecomment-1142463429
> Any thoughts about using a library like https://github.com/pytorch/cpuinfo to determine this information vs rolling our own?
Thanks you for the pointing of the library.
As for the question - on the one hand my patch fixes only Intel flow while AMD might still work wrong. And from this point of view it's better to reuse some solution which covers more platforms.
On the other hand for runtime - it's better to have as small solution as it can and it is unknown how lightweight pytorch/cpuinfo is. Even taking into account ability to be compiled into static library.
I would move forward with my patch and if we want to switch to pytorch/cpuinfo, we can do this later
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [tvm] tkonolige commented on a diff in pull request #11505: Fix max concurrency number in runtime for Intel processors
Posted by GitBox <gi...@apache.org>.
tkonolige commented on code in PR #11505:
URL: https://github.com/apache/tvm/pull/11505#discussion_r886020776
##########
src/runtime/threading_backend.cc:
##########
@@ -40,11 +40,158 @@
#define HEXAGON_STACK_ALIGNMENT 32
#endif
#include <algorithm>
+#include <string>
#include <thread>
#define CURRENT_THREAD_HANDLE (static_cast<std::thread::native_handle_type>(0))
namespace tvm {
namespace runtime {
namespace threading {
+#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
+#ifdef _MSC_VER
+#if (_MSC_VER < 1400)
+static inline __declspec(naked) void __cpuid(int[4], int) {
+ __asm {
+ push ebx
+ push esi
+ mov eax, dword ptr [esp + 4 * 2 + 8] // eaxIn
+ cpuid
+ mov esi, dword ptr [esp + 4 * 2 + 4] // data
+ mov dword ptr [esi], eax
+ mov dword ptr [esi + 4], ebx
+ mov dword ptr [esi + 8], ecx
+ mov dword ptr [esi + 12], edx
+ pop esi
+ pop ebx
+ ret
+ }
+}
+#else
+#include <intrin.h> // for __cpuid
+#endif
+#else
+#ifndef __GNUC_PREREQ
+#define __GNUC_PREREQ(major, minor) \
+ ((((__GNUC__) << 16) + (__GNUC_MINOR__)) >= (((major) << 16) + (minor)))
+#endif
+#if __GNUC_PREREQ(4, 3) && !defined(__APPLE__)
+#include <cpuid.h>
+#else
+// avoid err on Apple: can't find a register in class `BREG' while reloading `asm'
+#if defined(__APPLE__) && defined(_M_IX86)
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn), "2"(ecxIn))
+#else
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn), "2"(ecxIn))
+#endif
+#endif
+#endif
+
+unsigned int Cpu::get_num_cores(IntelCpuTopologyLevel level) const {
+ if (!x2apic_supported_) throw std::string("x2apic_supported_ is not supported");
+ switch (level) {
+ case SmtLevel:
+ return num_cores_[level - 1];
+ case CoreLevel:
+ return num_cores_[level - 1] / num_cores_[SmtLevel - 1];
+ default:
+ throw std::string("x2apic_supported_ is not supported");
+ }
+}
+
+/*
+ data[] = { eax, ebx, ecx, edx }
+*/
+void Cpu::get_cpuid(unsigned int eaxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuid(reinterpret_cast<int*>(data), eaxIn);
+#else
+ __cpuid(eaxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+void Cpu::get_cpuid_ex(unsigned int eaxIn, unsigned int ecxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuidex(reinterpret_cast<int*>(data), eaxIn, ecxIn);
+#else
+ __cpuid_count(eaxIn, ecxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+
+typedef uint64_t Type;
+static const Type NONE = 0;
+static const Type tINTEL = 1 << 24;
+static const Type tAMD = 1 << 25;
+
+Cpu::Cpu() : type_(NONE), x2apic_supported_(false), num_cores_() {
+ unsigned int data[4] = {};
+ const unsigned int& ECX = data[2];
+ get_cpuid(0, data);
+ static const char intel[] = "ntel";
+ static const char amd[] = "cAMD";
+ if (ECX == get32bit_ss_be(amd)) {
+ type_ |= tAMD;
+ }
+ if (ECX == get32bit_ss_be(intel)) {
+ type_ |= tINTEL;
+ }
+
+ set_num_cores();
+}
+bool Cpu::is_intel() { return type_ & tINTEL; }
+
+bool Cpu::is_amd() { return type_ & tAMD; }
+
+unsigned int Cpu::get32bit_ss_be(const char* x) const {
+ return x[0] | (x[1] << 8) | (x[2] << 16) | (x[3] << 24);
+}
+
+unsigned int Cpu::extract_bit(unsigned int val, unsigned int base, unsigned int end) {
+ return (val >> base) & ((1u << (end - base)) - 1);
+}
+
+void Cpu::set_num_cores() {
+ if ((type_ & tINTEL) == 0) return;
+
+ unsigned int data[4] = {};
+
+ /* CAUTION: These numbers are configuration as shipped by Intel. */
+ get_cpuid_ex(0x0, 0, data);
+ if (data[0] >= 0xB) {
+ /*
+ if leaf 11 exists(x2APIC is supported),
+ we use it to get the number of smt cores and cores on socket
+
+ leaf 0xB can be zeroed-out by a hypervisor
+ */
+ x2apic_supported_ = true;
+ for (unsigned int i = 0; i < max_topology_levels; i++) {
+ get_cpuid_ex(0xB, i, data);
+ IntelCpuTopologyLevel level = (IntelCpuTopologyLevel)extract_bit(data[2], 8, 15);
+ if (level == SmtLevel || level == CoreLevel) {
+ num_cores_[level - 1] = extract_bit(data[1], 0, 15);
+ }
+ }
+ /*
+ Fallback values in case a hypervisor has 0xB leaf zeroed-out.
+ */
+ num_cores_[SmtLevel - 1] = (std::max)(1u, num_cores_[SmtLevel - 1]);
Review Comment:
Could you explain why there are parens around `std::max`. Is this a C++ thing I am not familiar with?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [tvm] areusch commented on a diff in pull request #11505: Fix max concurrency number in runtime for Intel processors
Posted by GitBox <gi...@apache.org>.
areusch commented on code in PR #11505:
URL: https://github.com/apache/tvm/pull/11505#discussion_r894065722
##########
src/runtime/threading_backend.cc:
##########
@@ -40,11 +40,158 @@
#define HEXAGON_STACK_ALIGNMENT 32
#endif
#include <algorithm>
+#include <string>
#include <thread>
#define CURRENT_THREAD_HANDLE (static_cast<std::thread::native_handle_type>(0))
namespace tvm {
namespace runtime {
namespace threading {
+#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
+#ifdef _MSC_VER
+#if (_MSC_VER < 1400)
+static inline __declspec(naked) void __cpuid(int[4], int) {
+ __asm {
+ push ebx
+ push esi
+ mov eax, dword ptr [esp + 4 * 2 + 8] // eaxIn
+ cpuid
+ mov esi, dword ptr [esp + 4 * 2 + 4] // data
+ mov dword ptr [esi], eax
+ mov dword ptr [esi + 4], ebx
+ mov dword ptr [esi + 8], ecx
+ mov dword ptr [esi + 12], edx
+ pop esi
+ pop ebx
+ ret
+ }
+}
+#else
+#include <intrin.h> // for __cpuid
+#endif
+#else
+#ifndef __GNUC_PREREQ
+#define __GNUC_PREREQ(major, minor) \
+ ((((__GNUC__) << 16) + (__GNUC_MINOR__)) >= (((major) << 16) + (minor)))
+#endif
+#if __GNUC_PREREQ(4, 3) && !defined(__APPLE__)
+#include <cpuid.h>
+#else
+// avoid err on Apple: can't find a register in class `BREG' while reloading `asm'
+#if defined(__APPLE__) && defined(_M_IX86)
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn), "2"(ecxIn))
+#else
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn), "2"(ecxIn))
+#endif
+#endif
+#endif
+
+unsigned int Cpu::get_num_cores(IntelCpuTopologyLevel level) const {
+ if (!x2apic_supported_) throw std::string("x2apic_supported_ is not supported");
+ switch (level) {
+ case SmtLevel:
+ return num_cores_[level - 1];
+ case CoreLevel:
+ return num_cores_[level - 1] / num_cores_[SmtLevel - 1];
+ default:
+ throw std::string("x2apic_supported_ is not supported");
+ }
+}
+
+/*
+ data[] = { eax, ebx, ecx, edx }
+*/
+void Cpu::get_cpuid(unsigned int eaxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuid(reinterpret_cast<int*>(data), eaxIn);
+#else
+ __cpuid(eaxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+void Cpu::get_cpuid_ex(unsigned int eaxIn, unsigned int ecxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuidex(reinterpret_cast<int*>(data), eaxIn, ecxIn);
+#else
+ __cpuid_count(eaxIn, ecxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+
+typedef uint64_t Type;
+static const Type NONE = 0;
+static const Type tINTEL = 1 << 24;
+static const Type tAMD = 1 << 25;
+
+Cpu::Cpu() : type_(NONE), x2apic_supported_(false), num_cores_() {
+ unsigned int data[4] = {};
+ const unsigned int& ECX = data[2];
+ get_cpuid(0, data);
+ static const char intel[] = "ntel";
+ static const char amd[] = "cAMD";
+ if (ECX == get32bit_ss_be(amd)) {
+ type_ |= tAMD;
+ }
+ if (ECX == get32bit_ss_be(intel)) {
+ type_ |= tINTEL;
+ }
+
+ set_num_cores();
+}
+bool Cpu::is_intel() { return type_ & tINTEL; }
+
+bool Cpu::is_amd() { return type_ & tAMD; }
+
+unsigned int Cpu::get32bit_ss_be(const char* x) const {
+ return x[0] | (x[1] << 8) | (x[2] << 16) | (x[3] << 24);
+}
+
+unsigned int Cpu::extract_bit(unsigned int val, unsigned int base, unsigned int end) {
+ return (val >> base) & ((1u << (end - base)) - 1);
+}
+
+void Cpu::set_num_cores() {
+ if ((type_ & tINTEL) == 0) return;
+
+ unsigned int data[4] = {};
+
+ /* CAUTION: These numbers are configuration as shipped by Intel. */
+ get_cpuid_ex(0x0, 0, data);
+ if (data[0] >= 0xB) {
+ /*
+ if leaf 11 exists(x2APIC is supported),
+ we use it to get the number of smt cores and cores on socket
+
+ leaf 0xB can be zeroed-out by a hypervisor
+ */
+ x2apic_supported_ = true;
+ for (unsigned int i = 0; i < max_topology_levels; i++) {
+ get_cpuid_ex(0xB, i, data);
+ IntelCpuTopologyLevel level = (IntelCpuTopologyLevel)extract_bit(data[2], 8, 15);
+ if (level == SmtLevel || level == CoreLevel) {
+ num_cores_[level - 1] = extract_bit(data[1], 0, 15);
+ }
+ }
+ /*
+ Fallback values in case a hypervisor has 0xB leaf zeroed-out.
+ */
+ num_cores_[SmtLevel - 1] = (std::max)(1u, num_cores_[SmtLevel - 1]);
Review Comment:
cc @tqchen on this one
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [tvm] elvin-n commented on a diff in pull request #11505: Fix max concurrency number in runtime for Intel processors
Posted by GitBox <gi...@apache.org>.
elvin-n commented on code in PR #11505:
URL: https://github.com/apache/tvm/pull/11505#discussion_r886066507
##########
src/runtime/threading_backend.cc:
##########
@@ -40,11 +40,158 @@
#define HEXAGON_STACK_ALIGNMENT 32
#endif
#include <algorithm>
+#include <string>
#include <thread>
#define CURRENT_THREAD_HANDLE (static_cast<std::thread::native_handle_type>(0))
namespace tvm {
namespace runtime {
namespace threading {
+#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
+#ifdef _MSC_VER
+#if (_MSC_VER < 1400)
+static inline __declspec(naked) void __cpuid(int[4], int) {
+ __asm {
+ push ebx
+ push esi
+ mov eax, dword ptr [esp + 4 * 2 + 8] // eaxIn
+ cpuid
+ mov esi, dword ptr [esp + 4 * 2 + 4] // data
+ mov dword ptr [esi], eax
+ mov dword ptr [esi + 4], ebx
+ mov dword ptr [esi + 8], ecx
+ mov dword ptr [esi + 12], edx
+ pop esi
+ pop ebx
+ ret
+ }
+}
+#else
+#include <intrin.h> // for __cpuid
+#endif
+#else
+#ifndef __GNUC_PREREQ
+#define __GNUC_PREREQ(major, minor) \
+ ((((__GNUC__) << 16) + (__GNUC_MINOR__)) >= (((major) << 16) + (minor)))
+#endif
+#if __GNUC_PREREQ(4, 3) && !defined(__APPLE__)
+#include <cpuid.h>
+#else
+// avoid err on Apple: can't find a register in class `BREG' while reloading `asm'
+#if defined(__APPLE__) && defined(_M_IX86)
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn), "2"(ecxIn))
+#else
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn), "2"(ecxIn))
+#endif
+#endif
+#endif
+
+unsigned int Cpu::get_num_cores(IntelCpuTopologyLevel level) const {
+ if (!x2apic_supported_) throw std::string("x2apic_supported_ is not supported");
+ switch (level) {
+ case SmtLevel:
+ return num_cores_[level - 1];
+ case CoreLevel:
+ return num_cores_[level - 1] / num_cores_[SmtLevel - 1];
+ default:
+ throw std::string("x2apic_supported_ is not supported");
+ }
+}
+
+/*
+ data[] = { eax, ebx, ecx, edx }
+*/
+void Cpu::get_cpuid(unsigned int eaxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuid(reinterpret_cast<int*>(data), eaxIn);
+#else
+ __cpuid(eaxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+void Cpu::get_cpuid_ex(unsigned int eaxIn, unsigned int ecxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuidex(reinterpret_cast<int*>(data), eaxIn, ecxIn);
+#else
+ __cpuid_count(eaxIn, ecxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+
+typedef uint64_t Type;
+static const Type NONE = 0;
+static const Type tINTEL = 1 << 24;
+static const Type tAMD = 1 << 25;
+
+Cpu::Cpu() : type_(NONE), x2apic_supported_(false), num_cores_() {
+ unsigned int data[4] = {};
+ const unsigned int& ECX = data[2];
+ get_cpuid(0, data);
+ static const char intel[] = "ntel";
+ static const char amd[] = "cAMD";
+ if (ECX == get32bit_ss_be(amd)) {
+ type_ |= tAMD;
+ }
+ if (ECX == get32bit_ss_be(intel)) {
+ type_ |= tINTEL;
+ }
+
+ set_num_cores();
+}
+bool Cpu::is_intel() { return type_ & tINTEL; }
+
+bool Cpu::is_amd() { return type_ & tAMD; }
+
+unsigned int Cpu::get32bit_ss_be(const char* x) const {
+ return x[0] | (x[1] << 8) | (x[2] << 16) | (x[3] << 24);
+}
+
+unsigned int Cpu::extract_bit(unsigned int val, unsigned int base, unsigned int end) {
+ return (val >> base) & ((1u << (end - base)) - 1);
+}
+
+void Cpu::set_num_cores() {
+ if ((type_ & tINTEL) == 0) return;
+
+ unsigned int data[4] = {};
+
+ /* CAUTION: These numbers are configuration as shipped by Intel. */
+ get_cpuid_ex(0x0, 0, data);
+ if (data[0] >= 0xB) {
+ /*
+ if leaf 11 exists(x2APIC is supported),
+ we use it to get the number of smt cores and cores on socket
+
+ leaf 0xB can be zeroed-out by a hypervisor
+ */
+ x2apic_supported_ = true;
+ for (unsigned int i = 0; i < max_topology_levels; i++) {
+ get_cpuid_ex(0xB, i, data);
+ IntelCpuTopologyLevel level = (IntelCpuTopologyLevel)extract_bit(data[2], 8, 15);
+ if (level == SmtLevel || level == CoreLevel) {
+ num_cores_[level - 1] = extract_bit(data[1], 0, 15);
+ }
+ }
+ /*
+ Fallback values in case a hypervisor has 0xB leaf zeroed-out.
+ */
+ num_cores_[SmtLevel - 1] = (std::max)(1u, num_cores_[SmtLevel - 1]);
Review Comment:
Honestly saying, this part of code was taken from DNNL as is. But googling this - yes, it is a part of C++ and function names in parens are to avoid of ADL. https://quuxplusone.github.io/blog/2019/04/26/what-is-adl/
Like
```
namespace A {
struct A { operator int(); };
void f(A);
}
namespace B {
void f(int);
void f(double);
void test() {
A::A a;
void (*fp)(int) = f; // OK, no ADL
void (*gp)(A::A) = f; // ERROR, no ADL, fails to find A::f
f(a); // ADL, calls A::f(A)
(&f)(a); // no ADL, calls B::f(int)
(f)(a); // no ADL, calls B::f(int)
}
}
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [tvm] areusch commented on a diff in pull request #11505: Fix max concurrency number in runtime for Intel processors
Posted by GitBox <gi...@apache.org>.
areusch commented on code in PR #11505:
URL: https://github.com/apache/tvm/pull/11505#discussion_r896107952
##########
src/runtime/threading_backend.cc:
##########
@@ -40,11 +40,158 @@
#define HEXAGON_STACK_ALIGNMENT 32
#endif
#include <algorithm>
+#include <string>
#include <thread>
#define CURRENT_THREAD_HANDLE (static_cast<std::thread::native_handle_type>(0))
namespace tvm {
namespace runtime {
namespace threading {
+#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
+#ifdef _MSC_VER
+#if (_MSC_VER < 1400)
+static inline __declspec(naked) void __cpuid(int[4], int) {
+ __asm {
+ push ebx
+ push esi
+ mov eax, dword ptr [esp + 4 * 2 + 8] // eaxIn
+ cpuid
+ mov esi, dword ptr [esp + 4 * 2 + 4] // data
+ mov dword ptr [esi], eax
+ mov dword ptr [esi + 4], ebx
+ mov dword ptr [esi + 8], ecx
+ mov dword ptr [esi + 12], edx
+ pop esi
+ pop ebx
+ ret
+ }
+}
+#else
+#include <intrin.h> // for __cpuid
+#endif
+#else
+#ifndef __GNUC_PREREQ
+#define __GNUC_PREREQ(major, minor) \
+ ((((__GNUC__) << 16) + (__GNUC_MINOR__)) >= (((major) << 16) + (minor)))
+#endif
+#if __GNUC_PREREQ(4, 3) && !defined(__APPLE__)
+#include <cpuid.h>
+#else
+// avoid err on Apple: can't find a register in class `BREG' while reloading `asm'
+#if defined(__APPLE__) && defined(_M_IX86)
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn), "2"(ecxIn))
+#else
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn), "2"(ecxIn))
+#endif
+#endif
+#endif
+
+unsigned int Cpu::get_num_cores(IntelCpuTopologyLevel level) const {
+ if (!x2apic_supported_) throw std::string("x2apic_supported_ is not supported");
+ switch (level) {
+ case SmtLevel:
+ return num_cores_[level - 1];
+ case CoreLevel:
+ return num_cores_[level - 1] / num_cores_[SmtLevel - 1];
+ default:
+ throw std::string("x2apic_supported_ is not supported");
+ }
+}
+
+/*
+ data[] = { eax, ebx, ecx, edx }
+*/
+void Cpu::get_cpuid(unsigned int eaxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuid(reinterpret_cast<int*>(data), eaxIn);
+#else
+ __cpuid(eaxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+void Cpu::get_cpuid_ex(unsigned int eaxIn, unsigned int ecxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuidex(reinterpret_cast<int*>(data), eaxIn, ecxIn);
+#else
+ __cpuid_count(eaxIn, ecxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+
+typedef uint64_t Type;
+static const Type NONE = 0;
+static const Type tINTEL = 1 << 24;
+static const Type tAMD = 1 << 25;
+
+Cpu::Cpu() : type_(NONE), x2apic_supported_(false), num_cores_() {
+ unsigned int data[4] = {};
+ const unsigned int& ECX = data[2];
+ get_cpuid(0, data);
+ static const char intel[] = "ntel";
+ static const char amd[] = "cAMD";
+ if (ECX == get32bit_ss_be(amd)) {
+ type_ |= tAMD;
+ }
+ if (ECX == get32bit_ss_be(intel)) {
+ type_ |= tINTEL;
+ }
+
+ set_num_cores();
+}
+bool Cpu::is_intel() { return type_ & tINTEL; }
+
+bool Cpu::is_amd() { return type_ & tAMD; }
+
+unsigned int Cpu::get32bit_ss_be(const char* x) const {
+ return x[0] | (x[1] << 8) | (x[2] << 16) | (x[3] << 24);
+}
+
+unsigned int Cpu::extract_bit(unsigned int val, unsigned int base, unsigned int end) {
+ return (val >> base) & ((1u << (end - base)) - 1);
+}
+
+void Cpu::set_num_cores() {
+ if ((type_ & tINTEL) == 0) return;
+
+ unsigned int data[4] = {};
+
+ /* CAUTION: These numbers are configuration as shipped by Intel. */
+ get_cpuid_ex(0x0, 0, data);
+ if (data[0] >= 0xB) {
+ /*
+ if leaf 11 exists(x2APIC is supported),
+ we use it to get the number of smt cores and cores on socket
+
+ leaf 0xB can be zeroed-out by a hypervisor
+ */
+ x2apic_supported_ = true;
+ for (unsigned int i = 0; i < max_topology_levels; i++) {
+ get_cpuid_ex(0xB, i, data);
+ IntelCpuTopologyLevel level = (IntelCpuTopologyLevel)extract_bit(data[2], 8, 15);
+ if (level == SmtLevel || level == CoreLevel) {
+ num_cores_[level - 1] = extract_bit(data[1], 0, 15);
+ }
+ }
+ /*
+ Fallback values in case a hypervisor has 0xB leaf zeroed-out.
+ */
+ num_cores_[SmtLevel - 1] = (std::max)(1u, num_cores_[SmtLevel - 1]);
Review Comment:
i agree with @tkonolige that depending on a library that's specifically meant for reading CPU info like this is better than just a piece of a library because the update story is likely to be better. however, this could be bit more effort than was intended here. @elvin-n i'll let you choose which way to address this. we might update it later if the update story becomes complex.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [tvm] elvin-n commented on a diff in pull request #11505: Fix max concurrency number in runtime for Intel processors
Posted by GitBox <gi...@apache.org>.
elvin-n commented on code in PR #11505:
URL: https://github.com/apache/tvm/pull/11505#discussion_r887665866
##########
src/runtime/threading_backend.cc:
##########
@@ -40,11 +40,158 @@
#define HEXAGON_STACK_ALIGNMENT 32
#endif
#include <algorithm>
+#include <string>
#include <thread>
#define CURRENT_THREAD_HANDLE (static_cast<std::thread::native_handle_type>(0))
namespace tvm {
namespace runtime {
namespace threading {
+#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
+#ifdef _MSC_VER
+#if (_MSC_VER < 1400)
+static inline __declspec(naked) void __cpuid(int[4], int) {
+ __asm {
+ push ebx
+ push esi
+ mov eax, dword ptr [esp + 4 * 2 + 8] // eaxIn
+ cpuid
+ mov esi, dword ptr [esp + 4 * 2 + 4] // data
+ mov dword ptr [esi], eax
+ mov dword ptr [esi + 4], ebx
+ mov dword ptr [esi + 8], ecx
+ mov dword ptr [esi + 12], edx
+ pop esi
+ pop ebx
+ ret
+ }
+}
+#else
+#include <intrin.h> // for __cpuid
+#endif
+#else
+#ifndef __GNUC_PREREQ
+#define __GNUC_PREREQ(major, minor) \
+ ((((__GNUC__) << 16) + (__GNUC_MINOR__)) >= (((major) << 16) + (minor)))
+#endif
+#if __GNUC_PREREQ(4, 3) && !defined(__APPLE__)
+#include <cpuid.h>
+#else
+// avoid err on Apple: can't find a register in class `BREG' while reloading `asm'
+#if defined(__APPLE__) && defined(_M_IX86)
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn), "2"(ecxIn))
+#else
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn), "2"(ecxIn))
+#endif
+#endif
+#endif
+
+unsigned int Cpu::get_num_cores(IntelCpuTopologyLevel level) const {
+ if (!x2apic_supported_) throw std::string("x2apic_supported_ is not supported");
+ switch (level) {
+ case SmtLevel:
+ return num_cores_[level - 1];
+ case CoreLevel:
+ return num_cores_[level - 1] / num_cores_[SmtLevel - 1];
+ default:
+ throw std::string("x2apic_supported_ is not supported");
+ }
+}
+
+/*
+ data[] = { eax, ebx, ecx, edx }
+*/
+void Cpu::get_cpuid(unsigned int eaxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuid(reinterpret_cast<int*>(data), eaxIn);
+#else
+ __cpuid(eaxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+void Cpu::get_cpuid_ex(unsigned int eaxIn, unsigned int ecxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuidex(reinterpret_cast<int*>(data), eaxIn, ecxIn);
+#else
+ __cpuid_count(eaxIn, ecxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+
+typedef uint64_t Type;
+static const Type NONE = 0;
+static const Type tINTEL = 1 << 24;
+static const Type tAMD = 1 << 25;
+
+Cpu::Cpu() : type_(NONE), x2apic_supported_(false), num_cores_() {
+ unsigned int data[4] = {};
+ const unsigned int& ECX = data[2];
+ get_cpuid(0, data);
+ static const char intel[] = "ntel";
+ static const char amd[] = "cAMD";
+ if (ECX == get32bit_ss_be(amd)) {
+ type_ |= tAMD;
+ }
+ if (ECX == get32bit_ss_be(intel)) {
+ type_ |= tINTEL;
+ }
+
+ set_num_cores();
+}
+bool Cpu::is_intel() { return type_ & tINTEL; }
+
+bool Cpu::is_amd() { return type_ & tAMD; }
+
+unsigned int Cpu::get32bit_ss_be(const char* x) const {
+ return x[0] | (x[1] << 8) | (x[2] << 16) | (x[3] << 24);
+}
+
+unsigned int Cpu::extract_bit(unsigned int val, unsigned int base, unsigned int end) {
+ return (val >> base) & ((1u << (end - base)) - 1);
+}
+
+void Cpu::set_num_cores() {
+ if ((type_ & tINTEL) == 0) return;
+
+ unsigned int data[4] = {};
+
+ /* CAUTION: These numbers are configuration as shipped by Intel. */
+ get_cpuid_ex(0x0, 0, data);
+ if (data[0] >= 0xB) {
+ /*
+ if leaf 11 exists(x2APIC is supported),
+ we use it to get the number of smt cores and cores on socket
+
+ leaf 0xB can be zeroed-out by a hypervisor
+ */
+ x2apic_supported_ = true;
+ for (unsigned int i = 0; i < max_topology_levels; i++) {
+ get_cpuid_ex(0xB, i, data);
+ IntelCpuTopologyLevel level = (IntelCpuTopologyLevel)extract_bit(data[2], 8, 15);
+ if (level == SmtLevel || level == CoreLevel) {
+ num_cores_[level - 1] = extract_bit(data[1], 0, 15);
+ }
+ }
+ /*
+ Fallback values in case a hypervisor has 0xB leaf zeroed-out.
+ */
+ num_cores_[SmtLevel - 1] = (std::max)(1u, num_cores_[SmtLevel - 1]);
Review Comment:
@areusch do we have IP check? I would not like to introduce 3rd party component. As I said I significantly modified the code and it might be treated as new one.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [tvm] tqchen commented on a diff in pull request #11505: Fix max concurrency number in runtime for Intel processors
Posted by GitBox <gi...@apache.org>.
tqchen commented on code in PR #11505:
URL: https://github.com/apache/tvm/pull/11505#discussion_r894711056
##########
src/runtime/threading_backend.cc:
##########
@@ -40,11 +40,158 @@
#define HEXAGON_STACK_ALIGNMENT 32
#endif
#include <algorithm>
+#include <string>
#include <thread>
#define CURRENT_THREAD_HANDLE (static_cast<std::thread::native_handle_type>(0))
namespace tvm {
namespace runtime {
namespace threading {
+#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
+#ifdef _MSC_VER
+#if (_MSC_VER < 1400)
+static inline __declspec(naked) void __cpuid(int[4], int) {
+ __asm {
+ push ebx
+ push esi
+ mov eax, dword ptr [esp + 4 * 2 + 8] // eaxIn
+ cpuid
+ mov esi, dword ptr [esp + 4 * 2 + 4] // data
+ mov dword ptr [esi], eax
+ mov dword ptr [esi + 4], ebx
+ mov dword ptr [esi + 8], ecx
+ mov dword ptr [esi + 12], edx
+ pop esi
+ pop ebx
+ ret
+ }
+}
+#else
+#include <intrin.h> // for __cpuid
+#endif
+#else
+#ifndef __GNUC_PREREQ
+#define __GNUC_PREREQ(major, minor) \
+ ((((__GNUC__) << 16) + (__GNUC_MINOR__)) >= (((major) << 16) + (minor)))
+#endif
+#if __GNUC_PREREQ(4, 3) && !defined(__APPLE__)
+#include <cpuid.h>
+#else
+// avoid err on Apple: can't find a register in class `BREG' while reloading `asm'
+#if defined(__APPLE__) && defined(_M_IX86)
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn), "2"(ecxIn))
+#else
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn), "2"(ecxIn))
+#endif
+#endif
+#endif
+
+unsigned int Cpu::get_num_cores(IntelCpuTopologyLevel level) const {
+ if (!x2apic_supported_) throw std::string("x2apic_supported_ is not supported");
+ switch (level) {
+ case SmtLevel:
+ return num_cores_[level - 1];
+ case CoreLevel:
+ return num_cores_[level - 1] / num_cores_[SmtLevel - 1];
+ default:
+ throw std::string("x2apic_supported_ is not supported");
+ }
+}
+
+/*
+ data[] = { eax, ebx, ecx, edx }
+*/
+void Cpu::get_cpuid(unsigned int eaxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuid(reinterpret_cast<int*>(data), eaxIn);
+#else
+ __cpuid(eaxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+void Cpu::get_cpuid_ex(unsigned int eaxIn, unsigned int ecxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuidex(reinterpret_cast<int*>(data), eaxIn, ecxIn);
+#else
+ __cpuid_count(eaxIn, ecxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+
+typedef uint64_t Type;
+static const Type NONE = 0;
+static const Type tINTEL = 1 << 24;
+static const Type tAMD = 1 << 25;
+
+Cpu::Cpu() : type_(NONE), x2apic_supported_(false), num_cores_() {
+ unsigned int data[4] = {};
+ const unsigned int& ECX = data[2];
+ get_cpuid(0, data);
+ static const char intel[] = "ntel";
+ static const char amd[] = "cAMD";
+ if (ECX == get32bit_ss_be(amd)) {
+ type_ |= tAMD;
+ }
+ if (ECX == get32bit_ss_be(intel)) {
+ type_ |= tINTEL;
+ }
+
+ set_num_cores();
+}
+bool Cpu::is_intel() { return type_ & tINTEL; }
+
+bool Cpu::is_amd() { return type_ & tAMD; }
+
+unsigned int Cpu::get32bit_ss_be(const char* x) const {
+ return x[0] | (x[1] << 8) | (x[2] << 16) | (x[3] << 24);
+}
+
+unsigned int Cpu::extract_bit(unsigned int val, unsigned int base, unsigned int end) {
+ return (val >> base) & ((1u << (end - base)) - 1);
+}
+
+void Cpu::set_num_cores() {
+ if ((type_ & tINTEL) == 0) return;
+
+ unsigned int data[4] = {};
+
+ /* CAUTION: These numbers are configuration as shipped by Intel. */
+ get_cpuid_ex(0x0, 0, data);
+ if (data[0] >= 0xB) {
+ /*
+ if leaf 11 exists(x2APIC is supported),
+ we use it to get the number of smt cores and cores on socket
+
+ leaf 0xB can be zeroed-out by a hypervisor
+ */
+ x2apic_supported_ = true;
+ for (unsigned int i = 0; i < max_topology_levels; i++) {
+ get_cpuid_ex(0xB, i, data);
+ IntelCpuTopologyLevel level = (IntelCpuTopologyLevel)extract_bit(data[2], 8, 15);
+ if (level == SmtLevel || level == CoreLevel) {
+ num_cores_[level - 1] = extract_bit(data[1], 0, 15);
+ }
+ }
+ /*
+ Fallback values in case a hypervisor has 0xB leaf zeroed-out.
+ */
+ num_cores_[SmtLevel - 1] = (std::max)(1u, num_cores_[SmtLevel - 1]);
Review Comment:
unless the code is written in scratch, it would still be good to put into 3rdparty to be extra careful as long as there is no mechanism problems. The LICENSE seems to be fine, and we can add that to https://github.com/apache/tvm/tree/main/licenses
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [tvm] elvin-n commented on a diff in pull request #11505: Fix max concurrency number in runtime for Intel processors
Posted by GitBox <gi...@apache.org>.
elvin-n commented on code in PR #11505:
URL: https://github.com/apache/tvm/pull/11505#discussion_r896493516
##########
src/runtime/threading_backend.cc:
##########
@@ -40,11 +40,158 @@
#define HEXAGON_STACK_ALIGNMENT 32
#endif
#include <algorithm>
+#include <string>
#include <thread>
#define CURRENT_THREAD_HANDLE (static_cast<std::thread::native_handle_type>(0))
namespace tvm {
namespace runtime {
namespace threading {
+#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
+#ifdef _MSC_VER
+#if (_MSC_VER < 1400)
+static inline __declspec(naked) void __cpuid(int[4], int) {
+ __asm {
+ push ebx
+ push esi
+ mov eax, dword ptr [esp + 4 * 2 + 8] // eaxIn
+ cpuid
+ mov esi, dword ptr [esp + 4 * 2 + 4] // data
+ mov dword ptr [esi], eax
+ mov dword ptr [esi + 4], ebx
+ mov dword ptr [esi + 8], ecx
+ mov dword ptr [esi + 12], edx
+ pop esi
+ pop ebx
+ ret
+ }
+}
+#else
+#include <intrin.h> // for __cpuid
+#endif
+#else
+#ifndef __GNUC_PREREQ
+#define __GNUC_PREREQ(major, minor) \
+ ((((__GNUC__) << 16) + (__GNUC_MINOR__)) >= (((major) << 16) + (minor)))
+#endif
+#if __GNUC_PREREQ(4, 3) && !defined(__APPLE__)
+#include <cpuid.h>
+#else
+// avoid err on Apple: can't find a register in class `BREG' while reloading `asm'
+#if defined(__APPLE__) && defined(_M_IX86)
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn), "2"(ecxIn))
+#else
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn), "2"(ecxIn))
+#endif
+#endif
+#endif
+
+unsigned int Cpu::get_num_cores(IntelCpuTopologyLevel level) const {
+ if (!x2apic_supported_) throw std::string("x2apic_supported_ is not supported");
+ switch (level) {
+ case SmtLevel:
+ return num_cores_[level - 1];
+ case CoreLevel:
+ return num_cores_[level - 1] / num_cores_[SmtLevel - 1];
+ default:
+ throw std::string("x2apic_supported_ is not supported");
+ }
+}
+
+/*
+ data[] = { eax, ebx, ecx, edx }
+*/
+void Cpu::get_cpuid(unsigned int eaxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuid(reinterpret_cast<int*>(data), eaxIn);
+#else
+ __cpuid(eaxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+void Cpu::get_cpuid_ex(unsigned int eaxIn, unsigned int ecxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuidex(reinterpret_cast<int*>(data), eaxIn, ecxIn);
+#else
+ __cpuid_count(eaxIn, ecxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+
+typedef uint64_t Type;
+static const Type NONE = 0;
+static const Type tINTEL = 1 << 24;
+static const Type tAMD = 1 << 25;
+
+Cpu::Cpu() : type_(NONE), x2apic_supported_(false), num_cores_() {
+ unsigned int data[4] = {};
+ const unsigned int& ECX = data[2];
+ get_cpuid(0, data);
+ static const char intel[] = "ntel";
+ static const char amd[] = "cAMD";
+ if (ECX == get32bit_ss_be(amd)) {
+ type_ |= tAMD;
+ }
+ if (ECX == get32bit_ss_be(intel)) {
+ type_ |= tINTEL;
+ }
+
+ set_num_cores();
+}
+bool Cpu::is_intel() { return type_ & tINTEL; }
+
+bool Cpu::is_amd() { return type_ & tAMD; }
+
+unsigned int Cpu::get32bit_ss_be(const char* x) const {
+ return x[0] | (x[1] << 8) | (x[2] << 16) | (x[3] << 24);
+}
+
+unsigned int Cpu::extract_bit(unsigned int val, unsigned int base, unsigned int end) {
+ return (val >> base) & ((1u << (end - base)) - 1);
+}
+
+void Cpu::set_num_cores() {
+ if ((type_ & tINTEL) == 0) return;
+
+ unsigned int data[4] = {};
+
+ /* CAUTION: These numbers are configuration as shipped by Intel. */
+ get_cpuid_ex(0x0, 0, data);
+ if (data[0] >= 0xB) {
+ /*
+ if leaf 11 exists(x2APIC is supported),
+ we use it to get the number of smt cores and cores on socket
+
+ leaf 0xB can be zeroed-out by a hypervisor
+ */
+ x2apic_supported_ = true;
+ for (unsigned int i = 0; i < max_topology_levels; i++) {
+ get_cpuid_ex(0xB, i, data);
+ IntelCpuTopologyLevel level = (IntelCpuTopologyLevel)extract_bit(data[2], 8, 15);
+ if (level == SmtLevel || level == CoreLevel) {
+ num_cores_[level - 1] = extract_bit(data[1], 0, 15);
+ }
+ }
+ /*
+ Fallback values in case a hypervisor has 0xB leaf zeroed-out.
+ */
+ num_cores_[SmtLevel - 1] = (std::max)(1u, num_cores_[SmtLevel - 1]);
Review Comment:
I agree that there is no sense to add DNNL as third party for common tvm runtime. On the other hand it is not clear for me what is better - to rework this patch from the scratch or plug torch/cpuid. Will evaluate
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [tvm] elvin-n commented on a diff in pull request #11505: Fix max concurrency number in runtime for Intel processors
Posted by GitBox <gi...@apache.org>.
elvin-n commented on code in PR #11505:
URL: https://github.com/apache/tvm/pull/11505#discussion_r886150667
##########
src/runtime/threading_backend.cc:
##########
@@ -40,11 +40,158 @@
#define HEXAGON_STACK_ALIGNMENT 32
#endif
#include <algorithm>
+#include <string>
#include <thread>
#define CURRENT_THREAD_HANDLE (static_cast<std::thread::native_handle_type>(0))
namespace tvm {
namespace runtime {
namespace threading {
+#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
+#ifdef _MSC_VER
+#if (_MSC_VER < 1400)
+static inline __declspec(naked) void __cpuid(int[4], int) {
+ __asm {
+ push ebx
+ push esi
+ mov eax, dword ptr [esp + 4 * 2 + 8] // eaxIn
+ cpuid
+ mov esi, dword ptr [esp + 4 * 2 + 4] // data
+ mov dword ptr [esi], eax
+ mov dword ptr [esi + 4], ebx
+ mov dword ptr [esi + 8], ecx
+ mov dword ptr [esi + 12], edx
+ pop esi
+ pop ebx
+ ret
+ }
+}
+#else
+#include <intrin.h> // for __cpuid
+#endif
+#else
+#ifndef __GNUC_PREREQ
+#define __GNUC_PREREQ(major, minor) \
+ ((((__GNUC__) << 16) + (__GNUC_MINOR__)) >= (((major) << 16) + (minor)))
+#endif
+#if __GNUC_PREREQ(4, 3) && !defined(__APPLE__)
+#include <cpuid.h>
+#else
+// avoid err on Apple: can't find a register in class `BREG' while reloading `asm'
+#if defined(__APPLE__) && defined(_M_IX86)
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn), "2"(ecxIn))
+#else
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn), "2"(ecxIn))
+#endif
+#endif
+#endif
+
+unsigned int Cpu::get_num_cores(IntelCpuTopologyLevel level) const {
+ if (!x2apic_supported_) throw std::string("x2apic_supported_ is not supported");
+ switch (level) {
+ case SmtLevel:
+ return num_cores_[level - 1];
+ case CoreLevel:
+ return num_cores_[level - 1] / num_cores_[SmtLevel - 1];
+ default:
+ throw std::string("x2apic_supported_ is not supported");
+ }
+}
+
+/*
+ data[] = { eax, ebx, ecx, edx }
+*/
+void Cpu::get_cpuid(unsigned int eaxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuid(reinterpret_cast<int*>(data), eaxIn);
+#else
+ __cpuid(eaxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+void Cpu::get_cpuid_ex(unsigned int eaxIn, unsigned int ecxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuidex(reinterpret_cast<int*>(data), eaxIn, ecxIn);
+#else
+ __cpuid_count(eaxIn, ecxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+
+typedef uint64_t Type;
+static const Type NONE = 0;
+static const Type tINTEL = 1 << 24;
+static const Type tAMD = 1 << 25;
+
+Cpu::Cpu() : type_(NONE), x2apic_supported_(false), num_cores_() {
+ unsigned int data[4] = {};
+ const unsigned int& ECX = data[2];
+ get_cpuid(0, data);
+ static const char intel[] = "ntel";
+ static const char amd[] = "cAMD";
+ if (ECX == get32bit_ss_be(amd)) {
+ type_ |= tAMD;
+ }
+ if (ECX == get32bit_ss_be(intel)) {
+ type_ |= tINTEL;
+ }
+
+ set_num_cores();
+}
+bool Cpu::is_intel() { return type_ & tINTEL; }
+
+bool Cpu::is_amd() { return type_ & tAMD; }
+
+unsigned int Cpu::get32bit_ss_be(const char* x) const {
+ return x[0] | (x[1] << 8) | (x[2] << 16) | (x[3] << 24);
+}
+
+unsigned int Cpu::extract_bit(unsigned int val, unsigned int base, unsigned int end) {
+ return (val >> base) & ((1u << (end - base)) - 1);
+}
+
+void Cpu::set_num_cores() {
+ if ((type_ & tINTEL) == 0) return;
+
+ unsigned int data[4] = {};
+
+ /* CAUTION: These numbers are configuration as shipped by Intel. */
+ get_cpuid_ex(0x0, 0, data);
+ if (data[0] >= 0xB) {
+ /*
+ if leaf 11 exists(x2APIC is supported),
+ we use it to get the number of smt cores and cores on socket
+
+ leaf 0xB can be zeroed-out by a hypervisor
+ */
+ x2apic_supported_ = true;
+ for (unsigned int i = 0; i < max_topology_levels; i++) {
+ get_cpuid_ex(0xB, i, data);
+ IntelCpuTopologyLevel level = (IntelCpuTopologyLevel)extract_bit(data[2], 8, 15);
+ if (level == SmtLevel || level == CoreLevel) {
+ num_cores_[level - 1] = extract_bit(data[1], 0, 15);
+ }
+ }
+ /*
+ Fallback values in case a hypervisor has 0xB leaf zeroed-out.
+ */
+ num_cores_[SmtLevel - 1] = (std::max)(1u, num_cores_[SmtLevel - 1]);
Review Comment:
The code originally is taken from https://github.com/oneapi-src/oneDNN/blob/master/src/cpu/x64/xbyak/xbyak_util.h but later significantly modified to have only the required functionality and fit to tvm code style.
The dnnl itself has Apache license, but xbyak has its own license: https://github.com/oneapi-src/oneDNN/blob/master/src/cpu/x64/xbyak/COPYRIGHT
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [tvm] tkonolige commented on pull request #11505: Fix max concurrency number in runtime for Intel processors
Posted by GitBox <gi...@apache.org>.
tkonolige commented on PR #11505:
URL: https://github.com/apache/tvm/pull/11505#issuecomment-1142448960
Any thoughts about using a library like https://github.com/pytorch/cpuinfo to determine this information vs rolling our own? Either way, this is a nice addition to have!
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [tvm] tkonolige commented on pull request #11505: Fix max concurrency number in runtime for Intel processors
Posted by GitBox <gi...@apache.org>.
tkonolige commented on PR #11505:
URL: https://github.com/apache/tvm/pull/11505#issuecomment-1142500964
I totally agree on moving forward with this patch. I just wanted to see if there might be any issues adding this library in the future.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [tvm] tkonolige commented on a diff in pull request #11505: Fix max concurrency number in runtime for Intel processors
Posted by GitBox <gi...@apache.org>.
tkonolige commented on code in PR #11505:
URL: https://github.com/apache/tvm/pull/11505#discussion_r886090039
##########
src/runtime/threading_backend.cc:
##########
@@ -40,11 +40,158 @@
#define HEXAGON_STACK_ALIGNMENT 32
#endif
#include <algorithm>
+#include <string>
#include <thread>
#define CURRENT_THREAD_HANDLE (static_cast<std::thread::native_handle_type>(0))
namespace tvm {
namespace runtime {
namespace threading {
+#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
+#ifdef _MSC_VER
+#if (_MSC_VER < 1400)
+static inline __declspec(naked) void __cpuid(int[4], int) {
+ __asm {
+ push ebx
+ push esi
+ mov eax, dword ptr [esp + 4 * 2 + 8] // eaxIn
+ cpuid
+ mov esi, dword ptr [esp + 4 * 2 + 4] // data
+ mov dword ptr [esi], eax
+ mov dword ptr [esi + 4], ebx
+ mov dword ptr [esi + 8], ecx
+ mov dword ptr [esi + 12], edx
+ pop esi
+ pop ebx
+ ret
+ }
+}
+#else
+#include <intrin.h> // for __cpuid
+#endif
+#else
+#ifndef __GNUC_PREREQ
+#define __GNUC_PREREQ(major, minor) \
+ ((((__GNUC__) << 16) + (__GNUC_MINOR__)) >= (((major) << 16) + (minor)))
+#endif
+#if __GNUC_PREREQ(4, 3) && !defined(__APPLE__)
+#include <cpuid.h>
+#else
+// avoid err on Apple: can't find a register in class `BREG' while reloading `asm'
+#if defined(__APPLE__) && defined(_M_IX86)
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn), "2"(ecxIn))
+#else
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn), "2"(ecxIn))
+#endif
+#endif
+#endif
+
+unsigned int Cpu::get_num_cores(IntelCpuTopologyLevel level) const {
+ if (!x2apic_supported_) throw std::string("x2apic_supported_ is not supported");
+ switch (level) {
+ case SmtLevel:
+ return num_cores_[level - 1];
+ case CoreLevel:
+ return num_cores_[level - 1] / num_cores_[SmtLevel - 1];
+ default:
+ throw std::string("x2apic_supported_ is not supported");
+ }
+}
+
+/*
+ data[] = { eax, ebx, ecx, edx }
+*/
+void Cpu::get_cpuid(unsigned int eaxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuid(reinterpret_cast<int*>(data), eaxIn);
+#else
+ __cpuid(eaxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+void Cpu::get_cpuid_ex(unsigned int eaxIn, unsigned int ecxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuidex(reinterpret_cast<int*>(data), eaxIn, ecxIn);
+#else
+ __cpuid_count(eaxIn, ecxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+
+typedef uint64_t Type;
+static const Type NONE = 0;
+static const Type tINTEL = 1 << 24;
+static const Type tAMD = 1 << 25;
+
+Cpu::Cpu() : type_(NONE), x2apic_supported_(false), num_cores_() {
+ unsigned int data[4] = {};
+ const unsigned int& ECX = data[2];
+ get_cpuid(0, data);
+ static const char intel[] = "ntel";
+ static const char amd[] = "cAMD";
+ if (ECX == get32bit_ss_be(amd)) {
+ type_ |= tAMD;
+ }
+ if (ECX == get32bit_ss_be(intel)) {
+ type_ |= tINTEL;
+ }
+
+ set_num_cores();
+}
+bool Cpu::is_intel() { return type_ & tINTEL; }
+
+bool Cpu::is_amd() { return type_ & tAMD; }
+
+unsigned int Cpu::get32bit_ss_be(const char* x) const {
+ return x[0] | (x[1] << 8) | (x[2] << 16) | (x[3] << 24);
+}
+
+unsigned int Cpu::extract_bit(unsigned int val, unsigned int base, unsigned int end) {
+ return (val >> base) & ((1u << (end - base)) - 1);
+}
+
+void Cpu::set_num_cores() {
+ if ((type_ & tINTEL) == 0) return;
+
+ unsigned int data[4] = {};
+
+ /* CAUTION: These numbers are configuration as shipped by Intel. */
+ get_cpuid_ex(0x0, 0, data);
+ if (data[0] >= 0xB) {
+ /*
+ if leaf 11 exists(x2APIC is supported),
+ we use it to get the number of smt cores and cores on socket
+
+ leaf 0xB can be zeroed-out by a hypervisor
+ */
+ x2apic_supported_ = true;
+ for (unsigned int i = 0; i < max_topology_levels; i++) {
+ get_cpuid_ex(0xB, i, data);
+ IntelCpuTopologyLevel level = (IntelCpuTopologyLevel)extract_bit(data[2], 8, 15);
+ if (level == SmtLevel || level == CoreLevel) {
+ num_cores_[level - 1] = extract_bit(data[1], 0, 15);
+ }
+ }
+ /*
+ Fallback values in case a hypervisor has 0xB leaf zeroed-out.
+ */
+ num_cores_[SmtLevel - 1] = (std::max)(1u, num_cores_[SmtLevel - 1]);
Review Comment:
Didn't realize you were copying code from DNNL. Could you provide a link to the place you copied the code from and the license used by the code. Depending on the license you may need to include the license and provide attribution.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [tvm] elvin-n commented on pull request #11505: Fix max concurrency number in runtime for Intel processors
Posted by GitBox <gi...@apache.org>.
elvin-n commented on PR #11505:
URL: https://github.com/apache/tvm/pull/11505#issuecomment-1142511780
@tkonolige would you mind reviewing this PR? :)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix max concurrency number in runtime for Intel processors [tvm]
Posted by "tqchen (via GitHub)" <gi...@apache.org>.
tqchen closed pull request #11505: Fix max concurrency number in runtime for Intel processors
URL: https://github.com/apache/tvm/pull/11505
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [tvm] elvin-n commented on a diff in pull request #11505: Fix max concurrency number in runtime for Intel processors
Posted by GitBox <gi...@apache.org>.
elvin-n commented on code in PR #11505:
URL: https://github.com/apache/tvm/pull/11505#discussion_r886066507
##########
src/runtime/threading_backend.cc:
##########
@@ -40,11 +40,158 @@
#define HEXAGON_STACK_ALIGNMENT 32
#endif
#include <algorithm>
+#include <string>
#include <thread>
#define CURRENT_THREAD_HANDLE (static_cast<std::thread::native_handle_type>(0))
namespace tvm {
namespace runtime {
namespace threading {
+#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
+#ifdef _MSC_VER
+#if (_MSC_VER < 1400)
+static inline __declspec(naked) void __cpuid(int[4], int) {
+ __asm {
+ push ebx
+ push esi
+ mov eax, dword ptr [esp + 4 * 2 + 8] // eaxIn
+ cpuid
+ mov esi, dword ptr [esp + 4 * 2 + 4] // data
+ mov dword ptr [esi], eax
+ mov dword ptr [esi + 4], ebx
+ mov dword ptr [esi + 8], ecx
+ mov dword ptr [esi + 12], edx
+ pop esi
+ pop ebx
+ ret
+ }
+}
+#else
+#include <intrin.h> // for __cpuid
+#endif
+#else
+#ifndef __GNUC_PREREQ
+#define __GNUC_PREREQ(major, minor) \
+ ((((__GNUC__) << 16) + (__GNUC_MINOR__)) >= (((major) << 16) + (minor)))
+#endif
+#if __GNUC_PREREQ(4, 3) && !defined(__APPLE__)
+#include <cpuid.h>
+#else
+// avoid err on Apple: can't find a register in class `BREG' while reloading `asm'
+#if defined(__APPLE__) && defined(_M_IX86)
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn), "2"(ecxIn))
+#else
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn), "2"(ecxIn))
+#endif
+#endif
+#endif
+
+unsigned int Cpu::get_num_cores(IntelCpuTopologyLevel level) const {
+ if (!x2apic_supported_) throw std::string("x2apic_supported_ is not supported");
+ switch (level) {
+ case SmtLevel:
+ return num_cores_[level - 1];
+ case CoreLevel:
+ return num_cores_[level - 1] / num_cores_[SmtLevel - 1];
+ default:
+ throw std::string("x2apic_supported_ is not supported");
+ }
+}
+
+/*
+ data[] = { eax, ebx, ecx, edx }
+*/
+void Cpu::get_cpuid(unsigned int eaxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuid(reinterpret_cast<int*>(data), eaxIn);
+#else
+ __cpuid(eaxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+void Cpu::get_cpuid_ex(unsigned int eaxIn, unsigned int ecxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuidex(reinterpret_cast<int*>(data), eaxIn, ecxIn);
+#else
+ __cpuid_count(eaxIn, ecxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+
+typedef uint64_t Type;
+static const Type NONE = 0;
+static const Type tINTEL = 1 << 24;
+static const Type tAMD = 1 << 25;
+
+Cpu::Cpu() : type_(NONE), x2apic_supported_(false), num_cores_() {
+ unsigned int data[4] = {};
+ const unsigned int& ECX = data[2];
+ get_cpuid(0, data);
+ static const char intel[] = "ntel";
+ static const char amd[] = "cAMD";
+ if (ECX == get32bit_ss_be(amd)) {
+ type_ |= tAMD;
+ }
+ if (ECX == get32bit_ss_be(intel)) {
+ type_ |= tINTEL;
+ }
+
+ set_num_cores();
+}
+bool Cpu::is_intel() { return type_ & tINTEL; }
+
+bool Cpu::is_amd() { return type_ & tAMD; }
+
+unsigned int Cpu::get32bit_ss_be(const char* x) const {
+ return x[0] | (x[1] << 8) | (x[2] << 16) | (x[3] << 24);
+}
+
+unsigned int Cpu::extract_bit(unsigned int val, unsigned int base, unsigned int end) {
+ return (val >> base) & ((1u << (end - base)) - 1);
+}
+
+void Cpu::set_num_cores() {
+ if ((type_ & tINTEL) == 0) return;
+
+ unsigned int data[4] = {};
+
+ /* CAUTION: These numbers are configuration as shipped by Intel. */
+ get_cpuid_ex(0x0, 0, data);
+ if (data[0] >= 0xB) {
+ /*
+ if leaf 11 exists(x2APIC is supported),
+ we use it to get the number of smt cores and cores on socket
+
+ leaf 0xB can be zeroed-out by a hypervisor
+ */
+ x2apic_supported_ = true;
+ for (unsigned int i = 0; i < max_topology_levels; i++) {
+ get_cpuid_ex(0xB, i, data);
+ IntelCpuTopologyLevel level = (IntelCpuTopologyLevel)extract_bit(data[2], 8, 15);
+ if (level == SmtLevel || level == CoreLevel) {
+ num_cores_[level - 1] = extract_bit(data[1], 0, 15);
+ }
+ }
+ /*
+ Fallback values in case a hypervisor has 0xB leaf zeroed-out.
+ */
+ num_cores_[SmtLevel - 1] = (std::max)(1u, num_cores_[SmtLevel - 1]);
Review Comment:
Honestly saying, this part of code was taken from DNNL as is. But googling this - yes, it is a part of C++ and function names in parens are to avoid of ADL. https://quuxplusone.github.io/blog/2019/04/26/what-is-adl/
Like
```
namespace A {
struct A { operator int(); };
void f(A);
}
namespace B {
void f(int);
void f(double);
void test() {
A::A a;
void (*fp)(int) = f; // OK, no ADL
void (*gp)(A::A) = f; // ERROR, no ADL, fails to find A::f
**f(a); // ADL, calls A::f(A)**
(&f)(a); // no ADL, calls B::f(int)
**(f)(a); // no ADL, calls B::f(int)**
}
}
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [tvm] areusch commented on a diff in pull request #11505: Fix max concurrency number in runtime for Intel processors
Posted by GitBox <gi...@apache.org>.
areusch commented on code in PR #11505:
URL: https://github.com/apache/tvm/pull/11505#discussion_r887262357
##########
src/runtime/threading_backend.cc:
##########
@@ -40,11 +40,158 @@
#define HEXAGON_STACK_ALIGNMENT 32
#endif
#include <algorithm>
+#include <string>
#include <thread>
#define CURRENT_THREAD_HANDLE (static_cast<std::thread::native_handle_type>(0))
namespace tvm {
namespace runtime {
namespace threading {
+#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
+#ifdef _MSC_VER
+#if (_MSC_VER < 1400)
+static inline __declspec(naked) void __cpuid(int[4], int) {
+ __asm {
+ push ebx
+ push esi
+ mov eax, dword ptr [esp + 4 * 2 + 8] // eaxIn
+ cpuid
+ mov esi, dword ptr [esp + 4 * 2 + 4] // data
+ mov dword ptr [esi], eax
+ mov dword ptr [esi + 4], ebx
+ mov dword ptr [esi + 8], ecx
+ mov dword ptr [esi + 12], edx
+ pop esi
+ pop ebx
+ ret
+ }
+}
+#else
+#include <intrin.h> // for __cpuid
+#endif
+#else
+#ifndef __GNUC_PREREQ
+#define __GNUC_PREREQ(major, minor) \
+ ((((__GNUC__) << 16) + (__GNUC_MINOR__)) >= (((major) << 16) + (minor)))
+#endif
+#if __GNUC_PREREQ(4, 3) && !defined(__APPLE__)
+#include <cpuid.h>
+#else
+// avoid err on Apple: can't find a register in class `BREG' while reloading `asm'
+#if defined(__APPLE__) && defined(_M_IX86)
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn), "2"(ecxIn))
+#else
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn), "2"(ecxIn))
+#endif
+#endif
+#endif
+
+unsigned int Cpu::get_num_cores(IntelCpuTopologyLevel level) const {
+ if (!x2apic_supported_) throw std::string("x2apic_supported_ is not supported");
+ switch (level) {
+ case SmtLevel:
+ return num_cores_[level - 1];
+ case CoreLevel:
+ return num_cores_[level - 1] / num_cores_[SmtLevel - 1];
+ default:
+ throw std::string("x2apic_supported_ is not supported");
+ }
+}
+
+/*
+ data[] = { eax, ebx, ecx, edx }
+*/
+void Cpu::get_cpuid(unsigned int eaxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuid(reinterpret_cast<int*>(data), eaxIn);
+#else
+ __cpuid(eaxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+void Cpu::get_cpuid_ex(unsigned int eaxIn, unsigned int ecxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuidex(reinterpret_cast<int*>(data), eaxIn, ecxIn);
+#else
+ __cpuid_count(eaxIn, ecxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+
+typedef uint64_t Type;
+static const Type NONE = 0;
+static const Type tINTEL = 1 << 24;
+static const Type tAMD = 1 << 25;
+
+Cpu::Cpu() : type_(NONE), x2apic_supported_(false), num_cores_() {
+ unsigned int data[4] = {};
+ const unsigned int& ECX = data[2];
+ get_cpuid(0, data);
+ static const char intel[] = "ntel";
+ static const char amd[] = "cAMD";
+ if (ECX == get32bit_ss_be(amd)) {
+ type_ |= tAMD;
+ }
+ if (ECX == get32bit_ss_be(intel)) {
+ type_ |= tINTEL;
+ }
+
+ set_num_cores();
+}
+bool Cpu::is_intel() { return type_ & tINTEL; }
+
+bool Cpu::is_amd() { return type_ & tAMD; }
+
+unsigned int Cpu::get32bit_ss_be(const char* x) const {
+ return x[0] | (x[1] << 8) | (x[2] << 16) | (x[3] << 24);
+}
+
+unsigned int Cpu::extract_bit(unsigned int val, unsigned int base, unsigned int end) {
+ return (val >> base) & ((1u << (end - base)) - 1);
+}
+
+void Cpu::set_num_cores() {
+ if ((type_ & tINTEL) == 0) return;
+
+ unsigned int data[4] = {};
+
+ /* CAUTION: These numbers are configuration as shipped by Intel. */
+ get_cpuid_ex(0x0, 0, data);
+ if (data[0] >= 0xB) {
+ /*
+ if leaf 11 exists(x2APIC is supported),
+ we use it to get the number of smt cores and cores on socket
+
+ leaf 0xB can be zeroed-out by a hypervisor
+ */
+ x2apic_supported_ = true;
+ for (unsigned int i = 0; i < max_topology_levels; i++) {
+ get_cpuid_ex(0xB, i, data);
+ IntelCpuTopologyLevel level = (IntelCpuTopologyLevel)extract_bit(data[2], 8, 15);
+ if (level == SmtLevel || level == CoreLevel) {
+ num_cores_[level - 1] = extract_bit(data[1], 0, 15);
+ }
+ }
+ /*
+ Fallback values in case a hypervisor has 0xB leaf zeroed-out.
+ */
+ num_cores_[SmtLevel - 1] = (std::max)(1u, num_cores_[SmtLevel - 1]);
Review Comment:
@elvin-n for any third-party code we need to consult https://www.apache.org/legal/resolved.html. If the code can be accepted, then we need to place it under 3rdparty/ (submodule not needed if the original repo is documented) and update LICENSE. my guess is that including this code in apache/tvm repo might be tricky given the third-party policy above, but let me know if you see an avenue there.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [tvm] elvin-n commented on a diff in pull request #11505: Fix max concurrency number in runtime for Intel processors
Posted by GitBox <gi...@apache.org>.
elvin-n commented on code in PR #11505:
URL: https://github.com/apache/tvm/pull/11505#discussion_r887259604
##########
src/runtime/threading_backend.cc:
##########
@@ -40,11 +40,158 @@
#define HEXAGON_STACK_ALIGNMENT 32
#endif
#include <algorithm>
+#include <string>
#include <thread>
#define CURRENT_THREAD_HANDLE (static_cast<std::thread::native_handle_type>(0))
namespace tvm {
namespace runtime {
namespace threading {
+#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
+#ifdef _MSC_VER
+#if (_MSC_VER < 1400)
+static inline __declspec(naked) void __cpuid(int[4], int) {
+ __asm {
+ push ebx
+ push esi
+ mov eax, dword ptr [esp + 4 * 2 + 8] // eaxIn
+ cpuid
+ mov esi, dword ptr [esp + 4 * 2 + 4] // data
+ mov dword ptr [esi], eax
+ mov dword ptr [esi + 4], ebx
+ mov dword ptr [esi + 8], ecx
+ mov dword ptr [esi + 12], edx
+ pop esi
+ pop ebx
+ ret
+ }
+}
+#else
+#include <intrin.h> // for __cpuid
+#endif
+#else
+#ifndef __GNUC_PREREQ
+#define __GNUC_PREREQ(major, minor) \
+ ((((__GNUC__) << 16) + (__GNUC_MINOR__)) >= (((major) << 16) + (minor)))
+#endif
+#if __GNUC_PREREQ(4, 3) && !defined(__APPLE__)
+#include <cpuid.h>
+#else
+// avoid err on Apple: can't find a register in class `BREG' while reloading `asm'
+#if defined(__APPLE__) && defined(_M_IX86)
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" \
+ : "=a"(a), "=S"(b), "=c"(c), "=d"(d) \
+ : "0"(eaxIn), "2"(ecxIn))
+#else
+#define __cpuid(eaxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn))
+#define __cpuid_count(eaxIn, ecxIn, a, b, c, d) \
+ __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn), "2"(ecxIn))
+#endif
+#endif
+#endif
+
+unsigned int Cpu::get_num_cores(IntelCpuTopologyLevel level) const {
+ if (!x2apic_supported_) throw std::string("x2apic_supported_ is not supported");
+ switch (level) {
+ case SmtLevel:
+ return num_cores_[level - 1];
+ case CoreLevel:
+ return num_cores_[level - 1] / num_cores_[SmtLevel - 1];
+ default:
+ throw std::string("x2apic_supported_ is not supported");
+ }
+}
+
+/*
+ data[] = { eax, ebx, ecx, edx }
+*/
+void Cpu::get_cpuid(unsigned int eaxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuid(reinterpret_cast<int*>(data), eaxIn);
+#else
+ __cpuid(eaxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+void Cpu::get_cpuid_ex(unsigned int eaxIn, unsigned int ecxIn, unsigned int data[4]) {
+#ifdef _MSC_VER
+ __cpuidex(reinterpret_cast<int*>(data), eaxIn, ecxIn);
+#else
+ __cpuid_count(eaxIn, ecxIn, data[0], data[1], data[2], data[3]);
+#endif
+}
+
+typedef uint64_t Type;
+static const Type NONE = 0;
+static const Type tINTEL = 1 << 24;
+static const Type tAMD = 1 << 25;
+
+Cpu::Cpu() : type_(NONE), x2apic_supported_(false), num_cores_() {
+ unsigned int data[4] = {};
+ const unsigned int& ECX = data[2];
+ get_cpuid(0, data);
+ static const char intel[] = "ntel";
+ static const char amd[] = "cAMD";
+ if (ECX == get32bit_ss_be(amd)) {
+ type_ |= tAMD;
+ }
+ if (ECX == get32bit_ss_be(intel)) {
+ type_ |= tINTEL;
+ }
+
+ set_num_cores();
+}
+bool Cpu::is_intel() { return type_ & tINTEL; }
+
+bool Cpu::is_amd() { return type_ & tAMD; }
+
+unsigned int Cpu::get32bit_ss_be(const char* x) const {
+ return x[0] | (x[1] << 8) | (x[2] << 16) | (x[3] << 24);
+}
+
+unsigned int Cpu::extract_bit(unsigned int val, unsigned int base, unsigned int end) {
+ return (val >> base) & ((1u << (end - base)) - 1);
+}
+
+void Cpu::set_num_cores() {
+ if ((type_ & tINTEL) == 0) return;
+
+ unsigned int data[4] = {};
+
+ /* CAUTION: These numbers are configuration as shipped by Intel. */
+ get_cpuid_ex(0x0, 0, data);
+ if (data[0] >= 0xB) {
+ /*
+ if leaf 11 exists(x2APIC is supported),
+ we use it to get the number of smt cores and cores on socket
+
+ leaf 0xB can be zeroed-out by a hypervisor
+ */
+ x2apic_supported_ = true;
+ for (unsigned int i = 0; i < max_topology_levels; i++) {
+ get_cpuid_ex(0xB, i, data);
+ IntelCpuTopologyLevel level = (IntelCpuTopologyLevel)extract_bit(data[2], 8, 15);
+ if (level == SmtLevel || level == CoreLevel) {
+ num_cores_[level - 1] = extract_bit(data[1], 0, 15);
+ }
+ }
+ /*
+ Fallback values in case a hypervisor has 0xB leaf zeroed-out.
+ */
+ num_cores_[SmtLevel - 1] = (std::max)(1u, num_cores_[SmtLevel - 1]);
Review Comment:
@tkonolige should I add mentioning of MITSUNARI Shigeo and its license into any tvm file?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org