-
Notifications
You must be signed in to change notification settings - Fork 134
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'dev' of github.com:janhq/nitro into feat/python-runtime…
…-engine
- Loading branch information
Showing
68 changed files
with
12,667 additions
and
155 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
# CPU Info | ||
|
||
This source code provides a simple C++ program to retrieve and display information about the CPU, including the vendor, brand, number of cores, number of logical processors (threads), and supported instruction sets (e.g., SSE, AVX, AVX512). | ||
|
||
## Files | ||
|
||
### CPUID.h | ||
|
||
This header file contains the CPUID class, which abstracts the CPUID instruction. The class provides methods to retrieve the values of the EAX, EBX, ECX, and EDX registers after calling the CPUID instruction with a given function ID. | ||
|
||
### cpuinfo.cpp | ||
|
||
This source file implements the CPUInfo class, which uses the CPUID class to gather various CPU-related information. The main function prints this information in JSON format. | ||
|
||
## Building | ||
|
||
### Windows | ||
|
||
To build the project on Windows, you can use Microsoft Visual Studio or the Visual Studio Developer Command Prompt. | ||
|
||
**Using Visual Studio Developer Command Prompt** | ||
|
||
1. Open the Developer Command Prompt for Visual Studio. | ||
|
||
2. Navigate to the project directory: | ||
```cmd | ||
cd path\to\your\project\directory | ||
``` | ||
3. Compile the source code using the following command: | ||
```cmd | ||
cl cpuinfo.cpp /EHsc | ||
``` | ||
This will create the executable cpuinfo.exe in the current directory. | ||
### Linux | ||
To build the project on Linux, you need g++ (the GNU C++ compiler). | ||
1. Open a terminal. | ||
2. Navigate to the project directory: | ||
```bash | ||
cd path/to/your/project/directory | ||
``` | ||
3. Compile the code: | ||
```bash | ||
g++ cpuinfo.cpp -o cpuinfo | ||
``` | ||
This will create the executable cpuinfo in the current directory. | ||
## Running the Program | ||
### Windows | ||
After building the project, you can run the executable from the command prompt: | ||
```cmd | ||
cpuinfo.exe | ||
``` | ||
|
||
### Linux | ||
|
||
After building the project, you can run the executable from the terminal: | ||
|
||
```bash | ||
./cpuinfo | ||
``` | ||
|
||
## Example Output | ||
|
||
The program prints the CPU information in JSON format. Example output: | ||
|
||
```json | ||
{ | ||
"vendor": "GenuineIntel", | ||
"brand": "12th Gen Intel(R) Core(TM) i5-12400F", | ||
"cores": 6, | ||
"threads": 12, | ||
"is_hyperthreading": true, | ||
"instructions": { | ||
"SSE": true, | ||
"SSE2": true, | ||
"SSE3": true, | ||
"SSE41": true, | ||
"SSE42": true, | ||
"AVX": true, | ||
"AVX2": true, | ||
"AVX512": true | ||
} | ||
} | ||
``` | ||
|
||
## Notes | ||
- Ensure that your environment is properly set up for compiling C++ code. On Windows, this typically involves installing Visual Studio with the C++ build tools. On Linux, you need to have g++ installed. | ||
- The JSON output format is designed to be easy to parse and read. | ||
- In the `bin` directory, there are pre-built outputs. For Windows, the code is signed with our certificate. You can download and use it directly or build from source. |
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
#ifndef CPUID_H | ||
#define CPUID_H | ||
|
||
#ifdef _WIN32 | ||
#include <limits.h> | ||
#include <intrin.h> | ||
typedef unsigned __int32 uint32_t; | ||
#else | ||
#include <stdint.h> | ||
#endif | ||
|
||
class CPUID { | ||
uint32_t regs[4]; | ||
|
||
public: | ||
explicit CPUID(unsigned i) { | ||
#ifdef _WIN32 | ||
__cpuid((int *)regs, (int)i); | ||
#else | ||
asm volatile | ||
("cpuid" : "=a" (regs[0]), "=b" (regs[1]), "=c" (regs[2]), "=d" (regs[3]) | ||
: "a" (i), "c" (0)); | ||
// ECX is set to zero for CPUID function 4 | ||
#endif | ||
} | ||
|
||
const uint32_t &EAX() const {return regs[0];} | ||
const uint32_t &EBX() const {return regs[1];} | ||
const uint32_t &ECX() const {return regs[2];} | ||
const uint32_t &EDX() const {return regs[3];} | ||
}; | ||
|
||
#endif // CPUID_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
#include <algorithm> | ||
#include <iostream> | ||
#include <string> | ||
|
||
#ifdef _WIN32 | ||
#include <limits.h> | ||
#include <intrin.h> | ||
typedef unsigned __int32 uint32_t; | ||
#else | ||
#include <stdint.h> | ||
#endif | ||
|
||
using namespace std; | ||
|
||
#define MAX_INTEL_TOP_LVL 4 | ||
|
||
class CPUID { | ||
uint32_t regs[4]; | ||
|
||
public: | ||
explicit CPUID(unsigned funcId, unsigned subFuncId) { | ||
#ifdef _WIN32 | ||
__cpuidex((int *)regs, (int)funcId, (int)subFuncId); | ||
|
||
#else | ||
asm volatile | ||
("cpuid" : "=a" (regs[0]), "=b" (regs[1]), "=c" (regs[2]), "=d" (regs[3]) | ||
: "a" (funcId), "c" (subFuncId)); | ||
// ECX is set to zero for CPUID function 4 | ||
#endif | ||
} | ||
|
||
const uint32_t &EAX() const {return regs[0];} | ||
const uint32_t &EBX() const {return regs[1];} | ||
const uint32_t &ECX() const {return regs[2];} | ||
const uint32_t &EDX() const {return regs[3];} | ||
}; | ||
|
||
class CPUInfo { | ||
public: | ||
CPUInfo(); | ||
string vendor() const { return mVendorId; } | ||
string model() const { return mModelName; } | ||
int cores() const { return mNumCores; } | ||
float cpuSpeedInMHz() const { return mCPUMHz; } | ||
bool isSSE() const { return mIsSSE; } | ||
bool isSSE2() const { return mIsSSE2; } | ||
bool isSSE3() const { return mIsSSE3; } | ||
bool isSSE41() const { return mIsSSE41; } | ||
bool isSSE42() const { return mIsSSE42; } | ||
bool isAVX() const { return mIsAVX; } | ||
bool isAVX2() const { return mIsAVX2; } | ||
bool isAVX512() const { return mIsAVX512; } | ||
bool isHyperThreaded() const { return mIsHTT; } | ||
int logicalCpus() const { return mNumLogCpus; } | ||
|
||
private: | ||
// Bit positions for data extractions | ||
static const uint32_t SSE_POS = 0x02000000; | ||
static const uint32_t SSE2_POS = 0x04000000; | ||
static const uint32_t SSE3_POS = 0x00000001; | ||
static const uint32_t SSE41_POS = 0x00080000; | ||
static const uint32_t SSE42_POS = 0x00100000; | ||
static const uint32_t AVX_POS = 0x10000000; | ||
static const uint32_t AVX2_POS = 0x00000020; | ||
static const uint32_t AVX512_POS = 0x00010000; // AVX-512F bit in EBX from CPUID function 7 | ||
static const uint32_t LVL_NUM = 0x000000FF; | ||
static const uint32_t LVL_TYPE = 0x0000FF00; | ||
static const uint32_t LVL_CORES = 0x0000FFFF; | ||
|
||
// Attributes | ||
string mVendorId; | ||
string mModelName; | ||
int mNumSMT; | ||
int mNumCores; | ||
int mNumLogCpus; | ||
float mCPUMHz; | ||
bool mIsHTT; | ||
bool mIsSSE; | ||
bool mIsSSE2; | ||
bool mIsSSE3; | ||
bool mIsSSE41; | ||
bool mIsSSE42; | ||
bool mIsAVX; | ||
bool mIsAVX2; | ||
bool mIsAVX512; | ||
}; | ||
|
||
CPUInfo::CPUInfo() | ||
{ | ||
// Get vendor name EAX=0 | ||
CPUID cpuID0(0, 0); | ||
uint32_t HFS = cpuID0.EAX(); | ||
mVendorId += string((const char *)&cpuID0.EBX(), 4); | ||
mVendorId += string((const char *)&cpuID0.EDX(), 4); | ||
mVendorId += string((const char *)&cpuID0.ECX(), 4); | ||
// Get SSE instructions availability | ||
CPUID cpuID1(1, 0); | ||
mIsHTT = cpuID1.EDX() & AVX_POS; | ||
mIsSSE = cpuID1.EDX() & SSE_POS; | ||
mIsSSE2 = cpuID1.EDX() & SSE2_POS; | ||
mIsSSE3 = cpuID1.ECX() & SSE3_POS; | ||
mIsSSE41 = cpuID1.ECX() & SSE41_POS; | ||
mIsSSE42 = cpuID1.ECX() & SSE41_POS; | ||
mIsAVX = cpuID1.ECX() & AVX_POS; | ||
// Get AVX2 and AVX512 instructions availability | ||
CPUID cpuID7(7, 0); | ||
mIsAVX2 = cpuID7.EBX() & AVX2_POS; | ||
mIsAVX512 = cpuID7.EBX() & AVX512_POS; | ||
|
||
string upVId = mVendorId; | ||
for_each(upVId.begin(), upVId.end(), [](char& in) { in = ::toupper(in); }); | ||
// Get num of cores | ||
if (upVId.find("INTEL") != std::string::npos) { | ||
if(HFS >= 11) { | ||
for (int lvl=0; lvl<MAX_INTEL_TOP_LVL; ++lvl) { | ||
CPUID cpuID4(0x0B, lvl); | ||
uint32_t currLevel = (LVL_TYPE & cpuID4.ECX())>>8; | ||
switch(currLevel) { | ||
case 0x01: mNumSMT = LVL_CORES & cpuID4.EBX(); break; | ||
case 0x02: mNumLogCpus = LVL_CORES & cpuID4.EBX(); break; | ||
default: break; | ||
} | ||
} | ||
mNumCores = mNumLogCpus/mNumSMT; | ||
} else { | ||
if (HFS>=1) { | ||
mNumLogCpus = (cpuID1.EBX() >> 16) & 0xFF; | ||
if (HFS>=4) { | ||
mNumCores = 1 + (CPUID(4, 0).EAX() >> 26) & 0x3F; | ||
} | ||
} | ||
if (mIsHTT) { | ||
if (!(mNumCores>1)) { | ||
mNumCores = 1; | ||
mNumLogCpus = (mNumLogCpus >= 2 ? mNumLogCpus : 2); | ||
} | ||
} else { | ||
mNumCores = mNumLogCpus = 1; | ||
} | ||
} | ||
} else if (upVId.find("AMD") != std::string::npos) { | ||
if (HFS>=1) { | ||
mNumLogCpus = (cpuID1.EBX() >> 16) & 0xFF; | ||
if (CPUID(0x80000000, 0).EAX() >=8) { | ||
mNumCores = 1 + (CPUID(0x80000008, 0).ECX() & 0xFF); | ||
} | ||
} | ||
if (mIsHTT) { | ||
if (!(mNumCores>1)) { | ||
mNumCores = 1; | ||
mNumLogCpus = (mNumLogCpus >= 2 ? mNumLogCpus : 2); | ||
} | ||
} else { | ||
mNumCores = mNumLogCpus = 1; | ||
} | ||
} else { | ||
cout<< "Unexpected vendor id" <<endl; | ||
} | ||
// Get processor brand string | ||
// This seems to be working for both Intel & AMD vendors | ||
for(int i=0x80000002; i<0x80000005; ++i) { | ||
CPUID cpuID(i, 0); | ||
mModelName += string((const char*)&cpuID.EAX(), 4); | ||
mModelName += string((const char*)&cpuID.EBX(), 4); | ||
mModelName += string((const char*)&cpuID.ECX(), 4); | ||
mModelName += string((const char*)&cpuID.EDX(), 4); | ||
} | ||
} | ||
|
||
int main(int argc, char *argv[]) | ||
{ | ||
CPUInfo cinfo; | ||
|
||
cout << "{\n"; | ||
cout << " \"vendor\": \"" << cinfo.vendor() << "\",\n"; | ||
cout << " \"brand\": \"" << cinfo.model() << "\",\n"; | ||
cout << " \"cores\": " << cinfo.cores() << ",\n"; | ||
cout << " \"threads\": " << cinfo.logicalCpus() << ",\n"; | ||
cout << " \"is_hyperthreading\": " << (cinfo.isHyperThreaded() ? "true" : "false") << ",\n"; | ||
cout << " \"instructions\": {\n"; | ||
cout << " \"SSE\": " << (cinfo.isSSE() ? "true" : "false") << ",\n"; | ||
cout << " \"SSE2\": " << (cinfo.isSSE2() ? "true" : "false") << ",\n"; | ||
cout << " \"SSE3\": " << (cinfo.isSSE3() ? "true" : "false") << ",\n"; | ||
cout << " \"SSE41\": " << (cinfo.isSSE41() ? "true" : "false") << ",\n"; | ||
cout << " \"SSE42\": " << (cinfo.isSSE42() ? "true" : "false") << ",\n"; | ||
cout << " \"AVX\": " << (cinfo.isAVX() ? "true" : "false") << ",\n"; | ||
cout << " \"AVX2\": " << (cinfo.isAVX2() ? "true" : "false") << ",\n"; | ||
cout << " \"AVX512\": " << (cinfo.isAVX512() ? "true" : "false") << "\n"; | ||
cout << " }\n"; | ||
cout << "}\n"; | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
{ | ||
"vendor": "GenuineIntel", | ||
"brand": "12th Gen Intel(R) Core(TM) i5-12400F", | ||
"cores": 6, | ||
"threads": 12, | ||
"is_hyperthreading": true, | ||
"instructions": | ||
{ | ||
"SSE": true, | ||
"SSE2": true, | ||
"SSE3": true, | ||
"SSE41": true, | ||
"SSE42": true, | ||
"AVX": true, | ||
"AVX2": true, | ||
"AVX512": true | ||
} | ||
} |
Oops, something went wrong.