マルチコアCPU環境でのスレッド数
マルチスレッド自体は結構使っているのだが、パフォーマンスに関してはちゃんと測定したことがなかったので、簡単な測定プログラムを作って測ってみることにした。
今回は Windows 上で作業中だったので、WinAPI を使用している。
#ifdef _WINDOWS #include <Windows.h> #elif __MINGW32__ #include <windows.h> #include <winbase.h> #endif #include <process.h> #include <stdio.h> #include <xmmintrin.h> #include <emmintrin.h> const int VALUE = 90000000; const int thread_num = 2; const int NUM = 10; struct SSS { int start; int end; volatile bool work_start; volatile bool work_end; // bool work_start; // bool work_end; int* val; }; unsigned int __stdcall func(void* p) { SSS* s = (SSS*)p; while (!s->work_start) { Sleep(1); _mm_lfence(); } for (int i = 0; i < NUM; i++) { for (int j = s->start; j < s->end; j++) { s->val[j] = s->val[j] * s->val[j]; } } s->work_end = true; _mm_sfence(); return 0; } int main(int argc, char** argv) { SSS* s = new SSS[thread_num]; int* val = new int[VALUE]; for (int i = 0; i < thread_num; i++) { s[i].start = VALUE / thread_num * i + ((i == 0) ? 0 : 1); s[i].end = VALUE / thread_num * (i + 1); s[i].work_start = false; s[i].work_end = false; s[i].val = val; printf("s[%d].start = %d\n", i, s[i].start); printf("s[%d].end = %d\n", i, s[i].end); } for (int i = 0; i < VALUE; i++) { val[i] = i + 1; } HANDLE t[thread_num]; DWORD start_time = timeGetTime(); for (int i = 0; i < thread_num; i++) { t[i] = (HANDLE)_beginthreadex(NULL, 0, func, &s[i], 0, NULL); } printf("start : %d\n", start_time); for (int i = 0; i < thread_num; i++) { s[i].work_start = true; } _mm_sfence(); for (int i = 0; i < thread_num; i++) { s[i].val = val; } while (1) { bool end_ok = true; for (int i = 0; i < thread_num; i++) { if (!s[i].work_end) { end_ok = false; } } if (end_ok) { break; } Sleep(1); _mm_lfence(); } DWORD end_time = timeGetTime(); printf("end : %d\n", end_time); for (int i = 0; i < thread_num; i++) { WaitForSingleObject(t[i], INFINITE); } for (int i = 0; i < thread_num; i++) { CloseHandle(t[i]); } delete[] s; delete[] val; printf("time : %d\n", end_time - start_time); return 0; }
測定結果(5回だけ)
使用CPU : Pentium D 2.80GHz(2コア)
・1スレッド
time : 7265
time : 7344
time : 7312
time : 7360
time : 7297
・2スレッド
time : 4422
time : 4344
time : 4328
time : 4359
time : 4406
・5スレッド
time : 4360
time : 4328
time : 4343
time : 4297
time : 4390
・20スレッド
time : 4281
time : 4250
time : 4250
time : 4281
time : 4266
・100スレッド
time : 4234
time : 4250
time : 4234
time : 4250
time : 4234
大体1.6倍〜1.7倍ぐらいパフォーマンスが上がっている。
おそらく Core 2 Duo なら更に上がると思う。
本当は1コアや4コアでも動作確認がしたいのだが、手元にないので断念した。
このプログラムは単純なものだが、やはり重い処理をコア数より多くに分割しても意味がないようだ。
よく見ると、スレッド数が増えるごとに若干パフォーマンスは上がっているが、実用的なアプリケーションは裏で監視スレッドとか色々動いてたりするので、そっちに回したほうがいいだろう。
【追記】
64bit Linux + Mingw + wine でもやってみた。
・1スレッド
time : 6734
time : 6795
time : 6985
time : 6941
time : 6736
・2スレッド
time : 3891
time : 4014
time : 3753
time : 3782
time : 3807
Linux 上のほうがパフォーマンスが高くなったが、VC++ のデバッグコンパイルだし、色々と条件違うから仕方ないか。