山本ワールド
Windowsプログラミング
アルゴリズム Vitual C++ 2008/2013によるWin32/Win64 APIレベルのプログラム 基礎 Vitual C++ 2008/2013によるAPIレベルのプログラム(32/64bit) Wix3でインストーラーを作る Visual C++ 2008 Standard Editonによるフォームアプリケーションのプログラム(32/64bit) Vitual C++ 2008 Standard EditonによるAPIレベルのプログラム(32/64bit) Windows 7対応 Visual C++ 2008 ExpressによるAPIレベルのプログラム Visual C++ 2005 ExpressによるAPIレベルのプログラム Visual C++ Versiosn 5 BORLAND C++ Windowsプログラム全般 Excel VBA その他カレントスレッドのCPUを固定してプログラムを実行(32/64bit)
概要
マルチコアやハイパースレッド(HT)のCPUでシングルスレッドのプログラムを実行すると基本的には各CPUへ均等に割り当てられます。
実行CPUを固定すると、キャッシュやTLB等が有効に使われ実行速度の向上が期待できます。
本プログラムはカレントスレッドをCPU1に固定して重負荷の関数を約10秒実行します。実行には2個以上の論理プロセッサが必要です。
実行CPUを固定すると、キャッシュやTLB等が有効に使われ実行速度の向上が期待できます。
本プログラムはカレントスレッドをCPU1に固定して重負荷の関数を約10秒実行します。実行には2個以上の論理プロセッサが必要です。
テスト環境
コンパイラ
Visual C++ 2008/2013 Express 32/64bit マルチバイト/UNICODE実行環境
Windows XP Professional Service Pack 3 32bit(VirtualBox)Windows 7 Enterprise Service Pack 1 64bit(Sandy Bridge-E)
Windows 8.1 Enterprise 64bit(Arrandale)
プログラムソースの概要
WinMain
重負荷のtest1関数を呼び出します。test1
Corei7-3820(4.2GHz)で約18秒のループです。コンパイラの最適化によりループが削られないようにカウンタ用の変数はvolatile属性を付加しています。
GetCurrentThread APIにより自分自身のスレッドハンドルを取得します。
SetThreadAffinityMask APIの第2引数でどのCPUに割り当てるかを指定します。
ビット0がCPU0、ビット1がCPU1といったぐらいにビットごとにCPU番号が決まっており、該当ビットを1にするとそのCPUに割り当てられます。
この例では、1<<1としておりこれは1を1回左へシフトしますので、2となり1ビット目が1となります。
以下に第2引数の例を示します。
0x3 // CPU0 CPU1に割り当て
0x80 // CPU7に割り当て
0xff // CPU0~CPU7に割り当て
16<<7 // CPU7に割り当て
なお、SetThreadAffinityMask APIの第2引数は64bitなので64個以上のCPUは指定することができません。ソースコード
// CPU1に固定して実行
#include <windows.h>
// 重負荷の関数
void test1(void);
int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow){
test1();
return 0;
}
// 重負荷の関数
volatile int count1;
volatile int count2;
void test1(void){
HANDLE h;
h = GetCurrentThread();
SetThreadAffinityMask(h, 1 << 1);
for (count2 = 0; count2 < 10000; count2++)
for (count1 = 0; count1 < 1000000; count1++);
}
Copyright (C) 2012 山本ワールド All Rights Reserved.