もちゅるの日常

特に決まっていないざっくばらんなブログ

マルチスレッドとキャッシュ

 キャッシュを意識したプログラム。
どこかのサイトか忘れたけど、記事があったのでプログラム書いてみた。
要はメモリレベルでのスレッド間の独立性を高める。

ソース

#include <cstdio>
#include <process.h>
#include <Windows.h>
#include <conio.h>

// スレッド
#define THREAD_NUM  4
unsigned int __stdcall SubEntity0(void*);// スレッド0
unsigned int __stdcall SubEntity1(void*);// スレッド1
unsigned int __stdcall SubEntity2(void*);// スレッド2
unsigned int __stdcall SubEntity3(void*);// スレッド3
void func(const int idx );	// テスト用関数

// スレッドごとのアクセスデータ
//#define ST_SIZE		(1<<7) //128
#define ST_SIZE		(1<<5) //32
struct THREAD_DATA
{
	int cnt;
	unsigned char pad[ST_SIZE-sizeof(int)];
};
static THREAD_DATA s_threadData[THREAD_NUM] = {};

void main(void)
{
	int ver[(sizeof(THREAD_DATA)==ST_SIZE)?1:0] ={1};

	// スレッドリスト
	typedef unsigned int (__stdcall * ThreadEntry) (void *);
	ThreadEntry thread[THREAD_NUM] = {
		SubEntity0, SubEntity1, SubEntity2, SubEntity3,
	};


	printf("BLOCK SIZE:%d\n", ST_SIZE );
	int total = 0;
	for( int i = 0; i < 10; ++i )
	{
		HANDLE hSub[THREAD_NUM] = {};
		unsigned int sub[THREAD_NUM] = {};
		for( int x = 0; x < THREAD_NUM; ++x){
			hSub[x] = (HANDLE)_beginthreadex( NULL, 0, thread[x], NULL, 0, &sub[x] );
		}

		DWORD beginTime = timeGetTime();

		WaitForMultipleObjects(THREAD_NUM, hSub, TRUE, INFINITE );
		DWORD endTime = timeGetTime();
		printf("[%02d]DiffTime:%d\n", i, endTime-beginTime );
		total += endTime-beginTime;

		for(int x=0; x<THREAD_NUM; ++x){
			CloseHandle(hSub[x]);
		}
	}
	printf("Avg:%f", (float)total/10.0f);

	_getch();
}

unsigned int __stdcall SubEntity0(void*){
	func(0);
	_endthreadex(0);
	return 0;
}
unsigned int __stdcall SubEntity1(void*){
	func(1);
	_endthreadex(0);
	return 0;
}
unsigned int __stdcall SubEntity2(void*){
	func(2);
	_endthreadex(0);
	return 0;
}
unsigned int __stdcall SubEntity3(void*){
	func(3);
	_endthreadex(0);
	return 0;
}
void func(const int idx)
{
	for( int i = 0; i < 150000000; ++i){
		++s_threadData[idx].cnt;
		s_threadData[idx].cnt *= s_threadData[idx].cnt;
	}
}

結果

ブロックサイズ 時間[ms]
128 823.1ms
32 1356.0ms

まとめ

だいたいのマルチコアはコアごとにキャッシュを持っているので、
キャッシュがかぶらないようにある程度、アクセス領域を離す必要がある。
自分のPCではキャッシュの取得幅は128byteだった。
CPUによって取得サイズは異なると思う。システムから取得できる方法はあるか分からない。