プログラムでマシン上のコアの数を見つける


464

プラットフォームに依存しない方法で、C / C ++からマシンが持っているコアの数を決定する方法はありますか?そのようなものが存在しない場合、それをプラットフォームごと(Windows / * nix / Mac)に決定するのはどうですか?


4
使用するスレッドの数を調べたい場合は、NUMBER_OF_PROCESSORSを主な指標として使用してください。これは、ハードウェアコアを使用するよりもはるかに優れている理由(人々がより多く使用する場合)の練習問題として残しておきます。あなたのプログラムにどれだけのコアが属しているかは環境問題です!
Lothar

std::thread::hardware_concurrencyは物理CPUコアの数を返すことに注意してください。ただしnproc、Linuxでは、現在のプロセスが実行できるCPUコアの数のみが表示され、これはで制御できますsched_setaffinity。:私はそれではなく、標準C ++から:, Pythonで例えば参照を取得する方法を発見していないstackoverflow.com/questions/1006289/...
チロSantilli郝海东冠状病六四事件法轮功

回答:


706

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);
  • IRIX

    int numCPU = sysconf(_SC_NPROC_ONLN);
  • Objective-C(Mac OS X> = 10.5またはiOS)

    NSUInteger a = [[NSProcessInfo processInfo] processorCount];
    NSUInteger b = [[NSProcessInfo processInfo] activeProcessorCount];

5
@mcandre:それは読者のための演習として残されています。私が実装している場合は、プリプロセッサディレクティブでポリシーが定義されているテンプレートポリシーアプローチを使用するでしょう。または... boost thread :: hardware_concurrency()を使用できます。
paxos1977 2010年

3
明確にするために、Win32ソリューションは物理CPUの総数ではなく、コア(要求されたもの)の総数を返します。
エリック

1
Linux / Solaris / AIXの方法はFreeBSDでも機能し、少なくとも2006年から使用できます。また、システムがCPUをオフにできる場合、CPUはオンラインに戻されません。「_SC_NPROCESSORS_CONF」を指定してsysconfを呼び出すと、構成されているCPUの合計が返されます。
クリスS

3
注意すべきいくつかのこと。HW_NCPUはOS Xでは非推奨です。WindowsではGetSystemInfo、システムの論理プロセッサーが32以下の場合にのみ役立ちますGetLogicalProcessorInformation。論理プロセッサーが32を超えるシステムで使用します。

1
@Trejkazがdocumentaionが明確に「論理的」と言う-常にHTコアをカウントされ、単語「物理的には、」 常にコアを指しコアもエミュレートすることができるよう/仮想化BIOS / UEFIによって報告されました。たとえばGetLogicalProcessorInformationなどの関数を使用して、HTコアと非HTコアを区別できます。注:HT!=エミュレーションまたは仮想化、それは大きな違いです。HTは、いわばハードウェアの最適化です
専門家

202

この機能は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コアとハイパースレッディングユニットの数に基づいて、ハードウェアが同時に実行できるスレッドの数を返します。


1
出向しました...上のサンプルコードといくつかのプリプロセッサマクロを使用して単一の関数を公開するつもりでしたが、私のために大変な作業が行われました。
jkp 2009年

win32の場合、これはGetSystemInfoの呼び出しです。(ブーストバージョン1.41.0以降)有効なワーカースレッドの数を決定するためのすべての情報がキャプチャされますか?コアの数とハイパースレッディングの両方を考慮する必要がありますか?署名されていないスレッド:: hardware_concurrency(){SYSTEM_INFO info = {0}; GetSystemInfo(&info); info.dwNumberOfProcessorsを返します。}
Jive Dadson

MSDNによると、GetSystemInfo()は「物理プロセッサ」の数をdwNumberOfProcessorsに返しますが、それが何を意味するかは定義していません。Boostのドキュメントには、ハイパースレッディングユニットが含まれていると主張されているようです。
Ferruccio

ハイパースレッディングについては、stackoverflow.com
questions / 642348 /…を

57

OpenMPは多くのプラットフォーム(Visual Studio 2005を含む)でサポートされており、

int omp_get_num_procs();

呼び出し時に利用可能なプロセッサ/コアの数を返す関数。


それは間違った答えだからです。gcc.gnu.org/bugzilla/show_bug.cgi?id=37586から"omp_get_num_procs()は、GOMP_CPU_AFFINITY env varが使用されている場合、または呼び出しプロセスやスレッドにCPUアフィニティは、CPUのサブセットに制限されています。」したがって、たとえば以前に電話をかけた場合、sched_setaffinityこれは機能しません。
ゲイナー2013

7
この関数は、呼び出しプロセスで使用可能なCPUの数を返します。とにかく、それが最も一般的な使用例ではありませんか?一部の役に立たないレポート目的よりもサイズが大きいため、CPUハードウェアコアの実際の数は、コードでそれらを利用できない場合は関係ありません。
macbirdie 2013年

@EvanTeranそれが質問の目的であったという事実に加えて、それはもちろん役に立ちます。たとえば、スレッドアフィニティを設定するためです。私のマシンでは、最初の4つのコアではなく、最後の4つのCPUコアにバインドされた4つのスレッドを実行したいとします。さらに、OpenMP以外のコードを並列化する方法は他にもあります。自分でpthreadを生成したい場合があります。これらは確実に利用可能であり、OpenMP環境変数によって制限されません。
占領者2013年

2
これは、コア(物理CPU)自体ではなく、論理CPUの数を返します。
MichaelKonečný2016年

37

アセンブリ言語でアクセスできる場合は、CPUID命令を使用して、CPUに関するあらゆる種類の情報を取得できます。オペレーティングシステム間で移植可能ですが、製造元固有の情報を使用してコアの数を見つける方法を決定する必要があります。ここだIntelチップ上でそれを行う方法を説明した文書では、とのページ11 この1は AMDの仕様について説明します。


4
質問にはC ++のタグが付けられており、この回答はx86以外のアーキテクチャー(ARM、PPCなど)でC ++を実行しているシステムには適用されないため、反対票が投じられた可能性があります。答えを反対票を投じるのが正当な理由だと言っているのではなく、可能性だけです。
Ferruccio

3
この方法の落とし穴の1つは、CPUIDを使用してIntelプロセッサのハイパースレッディングを検出している場合です。私のラップトップでこの問題に遭遇しました:マシンに搭載したCPUはハイパースレッディングをサポートしていますが(もちろん、CPUIDを介してそれを報告します)、BIOSはサポートしていません。したがって、CPUIDを読み取るだけでHT機能を利用しようとするべきではありません。HTサポートについてBIOSに問い合わせることはできないので(私が見たことはありません)、論理プロセッサ数を取得するためにOSをクエリする必要があります。
チャックR

32

(ほぼ)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
}

思わHW_NCPUOS X用に推奨されませんソース

16

Linuxでは、/ proc / cpuinfoファイルを読み取ってコアをカウントできます。


ただし、ハイパースレッドまたはその他のSMTソリューションをより多くのコアとしてカウントすることを除いて...
jakobengblom2 '12 / 10/12

13
@Arafangion:ハイパースレッディングは真の並列実行ではなく、コンテキスト切り替えのオーバーヘッドを削減するためのテクノロジーです。ハイパースレッド化されたCPUは、一度に1つのスレッドしか実行できませんが、同時に2つのスレッドのアーキテクチャ状態(レジスタ値など)を格納できます。パフォーマンス特性は、2つのコアを持つ場合とは大きく異なります。
Wim Coenen、

7
@Wim:それは完全に正しくはありません。ハイパースレッディングを備えたCPUは、通常、複数のALUを持ち、サイクルごとに複数の命令をディスパッチできます。データの依存性とストールが原因で、1つのスレッドですべてのALUをビジー状態に保つことができない場合、それらのALUは2番目のハードウェアスレッドの同時実行に代わりに使用されます。
Ben Voigt

11

「コアの数」は特に有用な数ではないかもしれないことに注意してください。もう少し限定する必要があるかもしれません。Intel HT、IBM Power5、Power6、最も有名なSunのNiagara / UltraSparc T1およびT2などのマルチスレッドCPUをどのようにカウントしますか?またはさらに興味深いことに、ハードウェアスレッドの2つのレベル(スーパーバイザとユーザーレベル)を備えたMIPS 1004k ...ハードウェアに数十のCPUがある特定のOSであるハイパーバイザがサポートされているシステムに移行するとどうなるかは言うまでもありませんほんの少ししか見えません。

期待できる最善の方法は、ローカルOSパーティションにある論理処理装置の数を伝えることです。ハイパーバイザーでない限り、本当のマシンを見ることを忘れてください。今日のこのルールの唯一の例外はx86ランドですが、非仮想マシンの終焉が近づいています...


7

もう1つのWindowsレシピ:システム全体の環境変数を使用しますNUMBER_OF_PROCESSORS

printf("%d\n", atoi(getenv("NUMBER_OF_PROCESSORS")));

7

おそらく、プラットフォームに依存しない方法でそれを取得することはできません。Windowsでは、プロセッサーの数を取得します。

Win32システム情報


1
注意:ハイパースレッドプロセッサは2つあると言います。したがって、プロセッサがハイパースレッドに対応しているかどうかも確認する必要があります。
マーティンヨーク

6

Windows(x64およびWin32)およびC ++ 11

単一のプロセッサコアを共有する論理プロセッサのグループの数。(使用GetLogicalProcessorInformationExを参照してくださいGetLogicalProcessorInformationをも)

size_t NumberOfPhysicalCores() noexcept {

    DWORD length = 0;
    const BOOL result_first = GetLogicalProcessorInformationEx(RelationProcessorCore, nullptr, &length);
    assert(GetLastError() == ERROR_INSUFFICIENT_BUFFER);

    std::unique_ptr< uint8_t[] > buffer(new uint8_t[length]);
    const PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX info = 
            reinterpret_cast< PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX >(buffer.get());

    const BOOL result_second = GetLogicalProcessorInformationEx(RelationProcessorCore, info, &length);
    assert(result_second != FALSE);

    size_t nb_physical_cores = 0;
    size_t offset = 0;
    do {
        const PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX current_info =
            reinterpret_cast< PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX >(buffer.get() + offset);
        offset += current_info->Size;
        ++nb_physical_cores;
    } while (offset < length);

    return nb_physical_cores;
}

の実装はNumberOfPhysicalCores、些細なもの(つまり「使用」GetLogicalProcessorInformationまたはGetLogicalProcessorInformationEx「使用」)からIMHO であることに注意してください。代わりに、MSDN のドキュメント(明示的に存在しGetLogicalProcessorInformation、暗黙的に存在するGetLogicalProcessorInformationEx)をMSDNで読むと、かなり微妙です。

論理プロセッサーの数。GetSystemInfoを使用)

size_t NumberOfSystemCores() noexcept {
    SYSTEM_INFO system_info;
    ZeroMemory(&system_info, sizeof(system_info));

    GetSystemInfo(&system_info);

    return static_cast< size_t >(system_info.dwNumberOfProcessors);
}

どちらの方法も簡単にC / C ++ 98 / C ++ 03に変換できることに注意してください。


1
ありがとうございました!私がGetLogicalProcessorInformation使用していたさまざまなバッファサイズで作業していないため、これを探していました。満足以上!^^
KeyWeeUsr 2018

@KeyWeeUsrありがとうWindowsプログラミングは、些細で論理的なものとは程遠いものです。とりあえず、私は少し更新されたC ++ 17バージョンを使用しています。これは、一部のsize_tキャストに関して静的アナライザーPVS-Studioによるとより正確です。(ただし、msvc ++はW4で不満はありません。)
Matthias

5

OS Xの詳細:sysconf(_SC_NPROCESSORS_ONLN)10.4ではなく、10.5以上のバージョンでのみ利用できます。

代替は、HW_AVAILCPU/sysctl()バージョン10.2以上で利用可能なBSDコードです。



4

C ++とは無関係ですが、Linuxでは通常次のようにします。

grep processor /proc/cpuinfo | wc -l

bash / perl / python / ruby​​のようなスクリプト言語に便利です。


4
Pythonの場合:import multiprocessing print multiprocessing.cpu_count()
initzero

3
久しぶりですが、エントリー数をカウントするフラグがgrepあり-cます!
Lapshin Dmitry 2015

3

hwloc(http://www.open-mpi.org/projects/hwloc/)は一見の価値があります。ただし、コードに別のライブラリーを統合する必要がありますが、プロセッサーに関するすべての情報(コアの数、トポロジーなど)を提供できます。


3

Linuxで私が知る限り、プログラムによる最善の方法は使用することです

sysconf(_SC_NPROCESSORS_CONF)

または

sysconf(_SC_NPROCESSORS_ONLN)

これらは標準ではありませんが、Linuxの私のmanページにあります。


3

Linuxでは、_SC_NPROCESSORS_ONLNPOSIX標準の一部ではなく、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

2

OS Xの代替案:[[NSProcessInfo processInfo] processorCount]に基づいて前述したソリューションは、OS X 10.5.0でのみ利用できるとドキュメントに記載されています。以前のバージョンのOS Xでは、Carbon関数MPProcessors()を使用します。

Cocoaプログラマーであれば、これがCarbonであるという事実に驚かないでください。XcodeプロジェクトにCarbonフレームワークを追加する必要があるだけで、MPProcessors()が使用可能になります。



-2

.netでもWMIを使用できますが、実行中のwmiサービスなどに依存しています。ローカルで動作することもありますが、サーバーで同じコードを実行すると失敗します。それは名前空間の問題であり、あなたが読んでいる値の「名前」に関連していると思います。


-3

Linuxでは、dmesgをチェックアウトして、ACPIがCPUを初期化する行を次のようにフィルター処理できます。

dmesg | grep 'ACPI: Processor

その他の可能性は、dmidecodeを使用してプロセッサ情報を除外することです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.