プラットフォームに依存しない方法で、マシンが C/C++ から持っているコアの数を判断する方法はありますか? そのようなものが存在しない場合、プラットフォーム (Windows/*nix/Mac) ごとに決定するのはどうですか?
20 に答える
C++11
#include <thread>
//may return 0 when not able to detect
const auto processor_count = std::thread::hardware_concurrency();
参照: std::thread::hardware_concurrency
C++11 より前の C++ では、移植可能な方法はありません。代わりに、次のメソッドの 1 つ以上を使用する必要があります (適切な#ifdef
行で保護されています)。
Win32
SYSTEM_INFO sysinfo; GetSystemInfo(&sysinfo); int numCPU = sysinfo.dwNumberOfProcessors;
Linux、Solaris、AIX、および Mac OS X >=10.4 (つまり、Tiger 以降)
int numCPU = sysconf(_SC_NPROCESSORS_ONLN);
FreeBSD、MacOS X、NetBSD、OpenBSD など。
int mib[4]; int numCPU; std::size_t len = sizeof(numCPU); /* set the mib for hw.ncpu */ mib[0] = CTL_HW; mib[1] = HW_AVAILCPU; // alternatively, try HW_NCPU; /* get the number of CPUs from the system */ sysctl(mib, 2, &numCPU, &len, NULL, 0); if (numCPU < 1) { mib[1] = HW_NCPU; sysctl(mib, 2, &numCPU, &len, NULL, 0); if (numCPU < 1) numCPU = 1; }
HPUX
int numCPU = mpctl(MPC_GETNUMSPUS, NULL, NULL);
イリックス
int numCPU = sysconf(_SC_NPROC_ONLN);
Objective-C (Mac OS X >=10.5 または iOS)
NSUInteger a = [[NSProcessInfo processInfo] processorCount]; NSUInteger b = [[NSProcessInfo processInfo] activeProcessorCount];
この機能は C++11 標準の一部です。
#include <thread>
unsigned int nthreads = std::thread::hardware_concurrency();
古いコンパイラの場合は、Boost.Threadライブラリを使用できます。
#include <boost/thread.hpp>
unsigned int nthreads = boost::thread::hardware_concurrency();
どちらの場合も、hardware_concurrency()
CPU コアとハイパースレッディング ユニットの数に基づいて、ハードウェアが同時に実行できるスレッドの数を返します。
OpenMPは多くのプラットフォーム (Visual Studio 2005 を含む) でサポートされており、
int omp_get_num_procs();
呼び出し時に使用可能なプロセッサ/コアの数を返す関数。
アセンブリ言語にアクセスできる場合は、CPUID命令を使用して、CPUに関するあらゆる種類の情報を取得できます。オペレーティングシステム間で移植可能ですが、コアの数を見つける方法を決定するには、メーカー固有の情報を使用する必要があります。これはIntelチップでそれを行う方法を説明するドキュメントであり、このドキュメントの11ページはAMD仕様を説明しています。
(ほぼ) C コードのプラットフォームに依存しない関数
#ifdef _WIN32
#include <windows.h>
#elif MACOS
#include <sys/param.h>
#include <sys/sysctl.h>
#else
#include <unistd.h>
#endif
int getNumCores() {
#ifdef WIN32
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
return sysinfo.dwNumberOfProcessors;
#elif MACOS
int nm[2];
size_t len = 4;
uint32_t count;
nm[0] = CTL_HW; nm[1] = HW_AVAILCPU;
sysctl(nm, 2, &count, &len, NULL, 0);
if(count < 1) {
nm[1] = HW_NCPU;
sysctl(nm, 2, &count, &len, NULL, 0);
if(count < 1) { count = 1; }
}
return count;
#else
return sysconf(_SC_NPROCESSORS_ONLN);
#endif
}
Linux では、/proc/cpuinfo ファイルを読み取ってコアをカウントできます。
「コア数」は特に有用な数値ではない可能性があることに注意してください。もう少し修飾する必要があるかもしれません。Intel HT、IBM Power5 および Power6、そして最も有名な Sun の Niagara/UltraSparc T1 および T2 などのマルチスレッド CPU をどのようにカウントしますか? または、さらに興味深いのは、2 レベルのハードウェア スレッド (スーパーバイザー レベルとユーザー レベル) を備えた MIPS 1004k です。いくつかしか見えません。
期待できる最善の方法は、ローカル OS パーティションにある論理処理ユニットの数を伝えることです。ハイパーバイザーでない限り、実際のマシンを見ることは忘れてください。今日のこのルールの唯一の例外は x86 の世界ですが、非仮想マシンの終焉は急速に近づいています...
もう 1 つの Windows レシピ: システム全体の環境変数を使用しますNUMBER_OF_PROCESSORS
。
printf("%d\n", atoi(getenv("NUMBER_OF_PROCESSORS")));
おそらく、プラットフォームに依存しない方法で取得することはできません。Windows では、プロセッサの数を取得します。
C++ とは関係ありませんが、Linux では通常次のようにします。
grep processor /proc/cpuinfo | wc -l
bash/perl/python/ruby などのスクリプト言語に便利です。
OS X の詳細: sysconf(_SC_NPROCESSORS_ONLN)
10.4 ではなく、10.5 以降のバージョンでのみ利用できます。
代替手段は、HW_AVAILCPU/sysctl()
バージョン >= 10.2 で利用可能な BSD コードです。
Windows Server 2003 以降では、GetLogicalProcessorInformation 関数を利用できます
hwloc(http://www.open-mpi.org/projects/hwloc/)は一見の価値があります。コードに別のライブラリを統合する必要がありますが、プロセッサに関するすべての情報(コアの数、トポロジなど)を提供できます。
Linuxでは、私が知る限り、プログラムによる最良の方法は使用することです
sysconf(_SC_NPROCESSORS_CONF)
また
sysconf(_SC_NPROCESSORS_ONLN)
これらは標準ではありませんが、私の Linux の man ページにあります。
Linux では、これ_SC_NPROCESSORS_ONLN
は POSIX 標準の一部ではなく、sysconfのマニュアルにも記載されているため、安全に使用できない可能性があります。したがって、存在し_SC_NPROCESSORS_ONLN
ない可能性があります。
These values also exist, but may not be standard.
[...]
- _SC_NPROCESSORS_CONF
The number of processors configured.
- _SC_NPROCESSORS_ONLN
The number of processors currently online (available).
簡単なアプローチは、それらを読み取る/proc/stat
か/proc/cpuinfo
、カウントすることです。
#include<unistd.h>
#include<stdio.h>
int main(void)
{
char str[256];
int procCount = -1; // to offset for the first entry
FILE *fp;
if( (fp = fopen("/proc/stat", "r")) )
{
while(fgets(str, sizeof str, fp))
if( !memcmp(str, "cpu", 3) ) procCount++;
}
if ( procCount == -1)
{
printf("Unable to get proc count. Defaulting to 2");
procCount=2;
}
printf("Proc Count:%d\n", procCount);
return 0;
}
使用/proc/cpuinfo
:
#include<unistd.h>
#include<stdio.h>
int main(void)
{
char str[256];
int procCount = 0;
FILE *fp;
if( (fp = fopen("/proc/cpuinfo", "r")) )
{
while(fgets(str, sizeof str, fp))
if( !memcmp(str, "processor", 9) ) procCount++;
}
if ( !procCount )
{
printf("Unable to get proc count. Defaulting to 2");
procCount=2;
}
printf("Proc Count:%d\n", procCount);
return 0;
}
grep を使用したシェルでの同じアプローチ:
grep -c ^processor /proc/cpuinfo
または
grep -c ^cpu /proc/stat # subtract 1 from the result
OS Xの代替:ドキュメントによると、[[NSProcessInfoprocessInfo]processorCount]に基づく前述のソリューションはOSX10.5.0でのみ利用可能です。以前のバージョンのOSXの場合は、Carbon関数MPProcessors()を使用します。
あなたがCocoaプログラマーなら、これがCarbonであるという事実に驚かないでください。XcodeプロジェクトにCarbonフレームワークを追加するだけで、MPProcessors()が使用可能になります。
.netでもWMIを使用できますが、実行中のwmiサービスなどに依存しています。ローカルで機能することもありますが、同じコードがサーバーで実行されると失敗します。これは、値を読んでいる「名前」に関連する名前空間の問題だと思います。