我正在开发跨平台分析套件,并希望在每次运行的报告中添加有关机器CPU(架构/时钟速度/核心)和RAM(总计)的信息。目前我需要针对Windows和Unix,所以我需要从两个平台获取这些信息的方法,任何线索?
编辑:感谢您的答案,现在我获得了CPU体系结构,CPU核心数和内存总量,但是我仍然缺乏CPU的时钟速度吗?
答案 0 :(得分:8)
在Windows上,您可以使用GlobalMemoryStatusEx来获取实际RAM的数量。
处理器信息可以通过GetSystemInfo获得。
答案 1 :(得分:6)
在Windows上确定CPU时钟速度:
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;
}
答案 2 :(得分:5)
以下是在Windows计算机上获取所需信息的一种方法。我从实际项目中复制并粘贴了一些小修改,所以请随意清理它以使其更有意义。
int CPUInfo[4] = {-1};
unsigned nExIds, i = 0;
char CPUBrandString[0x40];
// Get the information associated with each extended ID.
__cpuid(CPUInfo, 0x80000000);
nExIds = CPUInfo[0];
for (i=0x80000000; i<=nExIds; ++i)
{
__cpuid(CPUInfo, i);
// Interpret CPU brand string
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));
}
//string includes manufacturer, model and clockspeed
cout << "CPU Type: " << CPUBrandString << endl;
SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
cout << "Number of Cores: " << sysInfo.dwNumberOfProcessors << endl;
MEMORYSTATUSEX statex;
statex.dwLength = sizeof (statex);
GlobalMemoryStatusEx(&statex);
cout << "Total System Memory: " << (statex.ullTotalPhys/1024)/1024 << "MB" << endl;
有关详细信息,请参阅GetSystemInfo,GlobalMemoryStatusEx和__cpuid。虽然我没有包含它,但您也可以通过GetSystemInfo函数确定操作系统是32位还是64位。
答案 3 :(得分:4)
CPU很简单。使用cpuid
指令。我将留下其他海报找到一种可移植的方式来确定系统有多少RAM。 : - )
对于特定于Linux的方法,如果您无法解析/proc/meminfo
响应,则可以访问/proc/cpuinfo
(和cpuid
。
答案 4 :(得分:3)
在Linux上,您可以解析/ proc / cpuinfo(包含每个处理器上的信息块)和/ proc / meminfo(包含各种常规内存统计信息,包括MemTotal)。
答案 5 :(得分:3)
对于使用GCC的Linux,您可以使用非常类似的解决方案,如Windows。您需要添加<cpuid.h>
,并且需要根据this修改__cpuid()
方法的输入。
#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;
答案 6 :(得分:1)
在Solaris上:
- 记忆
prtconf | grep Memory
- 对于CPU
psrinfo -v | grep MHz
答案 7 :(得分:1)
http://en.wikipedia.org/wiki/CPUID可能有助于CPUID
答案 8 :(得分:1)
OP希望在Windows和Linux之间移植CPU时钟速度计算程序。你走了:
#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));
}
显然这仅适用于x86 / x64,它依赖于TSC以与CPU相同的速度计数。如果你做了奇怪的超频事情,例如在我的超频FSB但降低倍频以使核心时钟保持规格,因此TSC将以FSB乘以最大倍数来计算得太快。
为了获得最佳效果,在运行GetClockSpeed()之前,我建议你运行一个反SpeedStep循环,例如。
usCount start;
start=GetUsCount();
while(GetUsCount()-start<3000000000000ULL);
CPUClockSpeed=GetClockSpeed();
尼尔
答案 9 :(得分:1)
我来晚了,但这是我的贡献。 我试图拥有一种更现代的C ++方法。
#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;
}
这是我自己执行此功能的结果: “英特尔®酷睿™i7-8700K CPU @ 3.70GHz”
老实说,这很烦人,但尚未标准化...
答案 10 :(得分:0)
我编写了一些使用WMI服务获取最大时钟速度的代码,我知道它是VB.net,但它显示了这个想法:
''' <summary>
''' Use WMI to get the Clock Speed in Hz
''' </summary>
Public Function GetMaxClockSpeedInHz() As Double
Dim manObj = New ManagementObject("Win32_Processor.DeviceID='CPU0'")
manObj.Get()
GetMaxClockSpeedInHz = Convert.ToInt32(manObj.Properties("MaxClockSpeed").Value)
End Function
Win32_OperatingSystem参考:http://msdn.microsoft.com/en-us/library/Aa394239
WMI参考:http://msdn.microsoft.com/en-us/library/aa394572(v=VS.85).aspx
答案 11 :(得分:0)
对于Windows和Win32 C ++项目:
上述URL和包含的文章演示了在Windows上检索CPU信息的3种不同方法。源代码位于本文的底部,编写得很好,并且有三个可以从Win32 C ++代码调用的有用类。
答案 12 :(得分:0)
此页面上bsruth最受欢迎的答案是使用__cpuid循环不必要地通过不需要的扩展功能。 如果您只需要知道处理器品牌字符串,则无需查询0x80000000。
Wikipedia很好地解释了示例代码: 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);
}
这是我想出的版本,可以直接将其转换为c ++中的std :: string
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;
此版本适用于linux,但使用__cpuid识别Windows应该不难