How to determine the hardware (CPU and RAM) on a machine?

前端 未结 13 844
长发绾君心
长发绾君心 2020-12-31 03:29

I\'m working on a cross platform profiling suite, and would like to add information about the machine\'s CPU (architecture/clock speed/cores) and RAM(total) to the report of

相关标签:
13条回答
  • 2020-12-31 03:48

    The most accepted answer by bsruth on this page using __cpuid loops unnecessarily through not needed extended functions. If all you need to know is the Processor Brand String then there is no need to query 0x80000000.

    Wikipedia has a nice explanation with example code: https://en.wikipedia.org/wiki/CPUID#EAX=80000002h,80000003h,80000004h:_Processor_Brand_String

    #include <cpuid.h>  // GCC-provided
    #include <stdio.h>
    #include <stdint.h>
    
    int main(void) {
        uint32_t brand[12];
    
        if (!__get_cpuid_max(0x80000004, NULL)) {
            fprintf(stderr, "Feature not implemented.");
            return 2;
        }
    
        __get_cpuid(0x80000002, brand+0x0, brand+0x1, brand+0x2, brand+0x3);
        __get_cpuid(0x80000003, brand+0x4, brand+0x5, brand+0x6, brand+0x7);
        __get_cpuid(0x80000004, brand+0x8, brand+0x9, brand+0xa, brand+0xb);
        printf("Brand: %s\n", brand);
    }
    

    and here is the version i came up with to directly convert it to a std::string in c++

    std::string CPUBrandString;
    CPUBrandString.resize(49);
    uint *CPUInfo = reinterpret_cast<uint*>(CPUBrandString.data());
    for (uint i=0; i<3; i++)
        __cpuid(0x80000002+i, CPUInfo[i*4+0], CPUInfo[i*4+1], CPUInfo[i*4+2], CPUInfo[i*4+3]);
    CPUBrandString.assign(CPUBrandString.data()); // correct null terminator
    std::cout << CPUBrandString << std::endl;
    

    this version is for linux, but it shouldn't be too hard to figure out for windows using __cpuid

    0 讨论(0)
  • 2020-12-31 03:48

    For Windows and Win32 C++ Projects:

    http://www.codeguru.com/cpp/w-p/system/hardwareinformation/article.php/c9087/Three-Ways-to-Retrieve-Processor-Information.htm

    The above URL and contained article demonstrates 3 different ways to retrieve CPU info on Windows. The source code is at the bottom of the article, is well written, and has three useful classes that you can call from your Win32 C++ code.

    0 讨论(0)
  • 2020-12-31 03:49

    The OP wants a CPU clock speed calculating routine portable between Windows and Linux. Here you go:

    #ifdef WIN32
    #define WIN32_LEAN_AND_MEAN
    #include <windows.h>
    typedef unsigned __int64 usCount;
    static usCount GetUsCount()
    {
        static LARGE_INTEGER ticksPerSec;
        static double scalefactor;
        LARGE_INTEGER val;
        if(!scalefactor)
        {
            if(QueryPerformanceFrequency(&ticksPerSec))
                scalefactor=ticksPerSec.QuadPart/1000000000000.0;
            else
                scalefactor=1;
        }
        if(!QueryPerformanceCounter(&val))
            return (usCount) GetTickCount() * 1000000000;
        return (usCount) (val.QuadPart/scalefactor);
    }
    #else
    #include <sys/time.h>
    #include <time.h>
    #include <sched.h>
    typedef unsigned long long usCount;
    static usCount GetUsCount()
    {
    #ifdef CLOCK_MONOTONIC
        struct timespec ts;
        clock_gettime(CLOCK_MONOTONIC, &ts);
        return ((usCount) ts.tv_sec*1000000000000LL)+ts.tv_nsec*1000LL;
    #else
        struct timeval tv;
        gettimeofday(&tv, 0);
        return ((usCount) tv.tv_sec*1000000000000LL)+tv.tv_usec*1000000LL;
    #endif
    }
    #endif
    static usCount usCountOverhead, CPUClockSpeed;
    #ifdef __GNUC__
    #include "x86intrin.h"
    #define __rdtsc() __builtin_ia32_rdtsc()
    #endif
    static usCount GetClockSpeed()
    {
      int n;
      usCount start, end, start_tsc, end_tsc;
      if(!usCountOverhead)
      {
        usCount foo=0;
        start=GetUsCount();
        for(n=0; n<1000000; n++)
        {
          foo+=GetUsCount();
        }
        end=GetUsCount();
        usCountOverhead=(end-start)/n;
      }
      start=GetUsCount();
      start_tsc=__rdtsc();
      for(n=0; n<1000; n++)
    #ifdef WIN32
        Sleep(0);
    #else
        sched_yield();
    #endif
      end_tsc=__rdtsc();
      end=GetUsCount();
      return (usCount)((1000000000000.0*(end_tsc-start_tsc))/(end-start-usCountOverhead));
    }
    

    Obviously this only works on x86/x64, and it relies on TSC counting at the same speed as the CPU. If you've done weird overclocking things e.g. on mine I overclock the FSB but downrate the multiplier to keep the core clock at spec, so TSC will count at FSB times the maximum multiplier which is too fast.

    To get the best results, before running GetClockSpeed() I'd suggest you run an anti-SpeedStep loop e.g.

    usCount start;
    start=GetUsCount();
    while(GetUsCount()-start<3000000000000ULL);
    CPUClockSpeed=GetClockSpeed();
    

    Niall

    0 讨论(0)
  • 2020-12-31 03:50

    On Windows to determine CPU clock speed:

    double CPUSpeed()
    {
        wchar_t Buffer[_MAX_PATH];
        DWORD BufSize = _MAX_PATH;
        DWORD dwMHz = _MAX_PATH;
        HKEY hKey;
    
        // open the key where the proc speed is hidden:
        long lError = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
                                    L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
                                    0,
                                    KEY_READ,
                                    &hKey);
        if(lError != ERROR_SUCCESS)
        {// if the key is not found, tell the user why:
            FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
                            NULL,
                            lError,
                            0,
                            Buffer,
                            _MAX_PATH,
                            0);
            wprintf(Buffer);
            return 0;
        }
    
        // query the key:
        RegQueryValueEx(hKey, L"~MHz", NULL, NULL, (LPBYTE) &dwMHz, &BufSize);
        return (double)dwMHz;
    }
    
    0 讨论(0)
  • 2020-12-31 03:54

    For Linux with GCC you can use a very similar solution like windows. You need to include the <cpuid.h> and you need to modify the input for the __cpuid() method based on this.

    #include <cpuid.h>
    
    char CPUBrandString[0x40];
    unsigned int CPUInfo[4] = {0,0,0,0};
    
    __cpuid(0x80000000, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]);
    unsigned int nExIds = CPUInfo[0];
    
    memset(CPUBrandString, 0, sizeof(CPUBrandString));
    
    for (unsigned int i = 0x80000000; i <= nExIds; ++i)
    {
        __cpuid(i, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]);
    
        if (i == 0x80000002)
            memcpy(CPUBrandString, CPUInfo, sizeof(CPUInfo));
        else if (i == 0x80000003)
            memcpy(CPUBrandString + 16, CPUInfo, sizeof(CPUInfo));
        else if (i == 0x80000004)
            memcpy(CPUBrandString + 32, CPUInfo, sizeof(CPUInfo));
    }
    
    cout << "CPU Type: " << CPUBrandString << endl;
    
    0 讨论(0)
  • 2020-12-31 03:57

    I'm very late but here is my contribution. I tried to have a more modern C++ approach.

        #include <intrin.h> // NOTE this header is MSVC specific!
        #include <string>
        #include <array>
    
        std::string GetCpuInfo()
        {
            // 4 is essentially hardcoded due to the __cpuid function requirements.
            // NOTE: Results are limited to whatever the sizeof(int) * 4 is...
            std::array<int, 4> integerBuffer = {};
            constexpr size_t sizeofIntegerBuffer = sizeof(int) * integerBuffer.size();
    
            std::array<char, 64> charBuffer = {};
    
            // The information you wanna query __cpuid for.
            // https://docs.microsoft.com/en-us/cpp/intrinsics/cpuid-cpuidex?view=vs-2019
            constexpr std::array<int, 3> functionIds = {
                // Manufacturer
                //  EX: "Intel(R) Core(TM"
                0x8000'0002,
                // Model
                //  EX: ") i7-8700K CPU @"
                0x8000'0003,
                // Clockspeed
                //  EX: " 3.70GHz"
                0x8000'0004
            };
    
            std::string cpu;
    
            for (int id : functionIds)
            {
                // Get the data for the current ID.
                __cpuid(integerBuffer.data(), id);
                
                // Copy the raw data from the integer buffer into the character buffer
                std::memcpy(charBuffer.data(), integerBuffer.data(), sizeofIntegerBuffer);
    
                // Copy that data into a std::string
                cpu += std::string(charBuffer.data());
            }
    
            return cpu;
        }
    

    Here was the result of this function for myself: "Intel(R) Core(TM) i7-8700K CPU @ 3.70GHz"

    Honestly it's really annoying something like this hasn't been standardized...

    0 讨论(0)
提交回复
热议问题