SSE2を使用し2ピクセル同時計算 H26.09.20

SSE2で倍精度浮動小数点を使用し水平方向の2ピクセルを同時計算してみた。
xmmレジスタの上位に1ピクセル目、下位に0ピクセル目を割り当てる。
ソースはインラインアセンブラで記述している。
大まかな概要を以下に示す。
xmmレジスタに格納されているデータについてはnがレジスタ番号とした場合、以下の様に表記する。
倍精度浮動小数点格納時 xmmn xmmnDH xmmnDL
単精度浮動小数点格納時 xmmn xmmn3 xmmn2 xmmn1 xmmn0
movsd命令で引数amax,aminを読み込む。amax,aminは64bitである。xmmレジスタの上位64bitは0でクリアされる。

xmmnH←0,xmmnL←amin
xmmnH←0,xmmnL←amax
subsd xmmd,xmms命令でamax-aminを実行。xmmレジスタの上位は0のままである。
xmmdH←xmmdH,xmmdL←xmmdL-xmmsL
cvtsi2sd xmmn命令で32bit整数scrxを倍精度小数点に変換してxmmレジスタ下位64bitに読み込む。xmmレジスタの上位は0クリアされる
xmmnH←xmmnH,xmmnL←32bit整数を倍精度浮動小数点に変換
divsd xmmd,xmms命令で除算をする。xmmレジスタの下位64bitには商(astep)が保存される。
xmmdH←xmmdH,xmmdL←xmmdL/xmmsL
shufpd xmmd,xmms,imm8命令でxmmレジスタの下位の値を下位と上位それぞれにコピーする。
imm8の0ビット目が0の場合はxmmdLにxmmdLが1の場合はxmmdHがコピーされる。
imm8の1ビット目が0の場合はxmmdHにxmmsLが1の場合はxmmsHがコピーされる。
xmmdH←xmmsL,xmmdL←xmmsL
addpd xmmd,xmms命令でxmm0=xmm0+xmm1を計算する。xmm0の上位・下位はamin、xmm1の上位は0,xmm1の下位は商である。
xmmdH←xmmdH+xmmsL,xmmdL←xmmdL+xmmsL
shufpd命令で上位と下位を入れ替える。すなわち下位はamin、上位はamin+astepとなる。
imm8の0ビット目が0の場合はxmmdLにxmmdLが1の場合はxmmdHがコピーされる。
imm8の1ビット目が0の場合はxmmdHにxmmsLが1の場合はxmmsHがコピーされる。
xmmdH←xmmsL,xmmdL←xmmsH
movaps an,xmmn命令でxmm0を変数anにコピーする。
anH←xmmnH,anL←xmmnL
SSE2で2ピクセル同時に計算するのでastepの値をaddpdで2倍にする。
bmin、bmaxについてもamin、amaxと同様に計算する。
ラベルy_loop
movsd命令でループを抜け出すリミット値をxmmレジスタの下位に読み出す。
shufpd命令でxmmレジスタの上位と下位に下位の値をコピーする。
xorpd命令でxmmレジスタを0クリアすることによりx,y,count値を0クリアする。
ラベルLOOP_L1:
各SSE2命令を使って計算する。
cmpltpd命令でリミット値と比較する。真の場合は64bit全部のビットが1にセットされる。
anH←xmmnH,anL←xmmnL
movmskpd命令で上位64bit値の最上位bitをedxの1bit目へ、下位64bit値の最上位bitをedxの0bit目へコピーする。
test命令でedxのビット値が1のビットがあるかチェックする。
jz命令によりedxに1がなければLOOP_L1_EXITラベルへジャンプする。(2ピクセルとも計算が終了したのでループを抜ける。)
movq命令によりxmmの下位64bitに10進数で1を読み込む。
pshufd命令でxmmレジスタの上位と下位に下位の値をコピーする。
cmpltpd命令の結果とpshufd命令の結果をpand命令でAND演算をする。そうするとリミット値を超えていないばあい、整数の1でこれている場合は0となる。
これによりリミット値を超えていない場合はcount値が増えリミット値を超えているとカウント値は増えない。
paddq命令によりpand命令の値とcount値を加算する。
ラベルLOOP_L1にジャンプする。
ラベルLOOP_L1_EXIT
xmmレジスタの上位に1ピクセル目、下位に0ピクセル目のカウント値が保存されているのでこれを色に変換する
メモリ上では1ピクセル4byteで表現しているが、カウント値は64bitなので32bitのみ有効とみなし、shufps命令によりxmmレジスタの0~31bitへxmmレジスタの0~31bitの値、xmmレジスタの32~61bitへxmmレジスタの64~95bitの値をコピーする。

ソースファイル、リソースファイル、実行ファイルダウンロード

 

マンデルブロ描画プログラム Version 2.00 H26.04.09

Version 1から以下の改良を行いました。
SSEを使用して4ピクセル同時計算を実現
bmpファイル保存ができるように修正
縦の画素数が4の倍数でない場合、マルチスレッドで計算する場合にエラーが発生する点を修正
Visual C++ 2008のUnicode 32bitに移植。アセンブラはMASM向けに変更
各種設定を1つのダイアログボックスにまとめた。
色の割り付けのバグを修正
ベンチマーク用に設定値を初期化できるように修正
計算時間を1秒より小さい単位で測定できるように修正

ソースファイル、リソースファイル、実行ファイルダウンロード

SSEを使用し4ピクセル同時計算 H26.09.20

SSEで単精度浮動小数点を使用し水平方向の4ピクセルを同時計算してみた。
SSEでは128bitのレジスタを8本が使用でき、1つのレジスタには単精度浮動小数点を4個保存できる。
プログラムはインラインアセンブラを使用した。計算部分のみのソースを示す。
FPU版と計算部分の関数は引数が同一なので、置き換えは容易である。
C++版も作成して速度の比較をした。
FPU版とC++版は倍精度、SSE版は単精度なので単純比較はできないが、それでもSSE版は高速である。
FPUとC++では優位な速度差がない。C++でも十分な速度がでるので、FPUの優位性が感じられない。
計算条件 800*600ピクセル a=-1.3333~1.3333 b=-1.0~1.0 反復回数最大32768

各CPUの演算性能

各世代のCPUでフラクタルを1スレッドで実行した場合の速度をクロックに影響されないように1GHzに換算してみた。値が小さいほど高速である。
Pentium4の遅さが目立つ。他のCPUでは1GHzあたりで換算すると速度はほぼ同一である。i3-370MについてはOSをバージョンアップしたので再度測定した。(H26.09.20)
CPUclockFPUSSE
i5-3230M2.6GHz(3.2GHz)7917
i7-38203.6GHz(4.2GHz)6415
i7-26003.6GHz(3.8GHz)6415
i3-370M2.4GHz6315
i7-8702.93GHz(3.6GHz)6315
Core2Duo E75002.93GHz6717
Core2Duo E63201.86GHz6618
Pentium4 6413.2GHz16237

i5-3230M(2.6GHz) Ivy Bridge

CPUC++FPUSSE速度比(FPU/SSE)
1スレッド24.44524.8355.454.56
2スレッド12.2312.4962.7454.55
4スレッド10.48310.9672.6364.16
8スレッド8.0979.4852.6063.64
16スレッド7.0828.2052.3093.55
32スレッド6.8647.9872.2943.48

i7-3820(オーバークロック4.2GHz) Sandy Bridge-E

CPUC++FPUSSESSE2速度比(FPU/SSE)
1スレッド15.07815.2953.63712.9064.205
2スレッド7.6097.7691.8466.7664.209
4スレッド6.3396.5681.6073.1604.087
8スレッド4.1004.3091.0772.1554.001

i7-2600(3.8GHz) Sandy Bridge

CPUC++FPUSSESSE2速度比(FPU/SSE)
1スレッド17.08217.0824.0567.9724.146
2スレッド8.6438.7832.1064.134.104
4スレッド7.2697.4731.7633.6204.123
8スレッド4.6484.8521.2012.3403.870

i3-370M(2.40GHz) Arrandale

CPUFPUSSESSE2速度比(FPU/SSE)
1スレッド26.0946.35912.9064.103
2スレッド14.4853.3126.7664.373
4スレッド12.6722.9846.2814.247
8スレッド11.0002.6885.5474.092

i7-870(2.93GHz) Lynnfield

CPUFPUSSE速度比(FPU/SSE)
1スレッド17.5824.2284.158
2スレッド9.222.2314.133
4スレッド8.0031.954.104
8スレッド5.7411.4513.957

Core2Duo E7500(2.93GHz) Wolfdale

CPUFPUSSEC++速度比(FPU/SSE)
1スレッド22.7455.9623.8683.82
2スレッド11.423.01111.9813.79
4スレッド11.3883.52611.953.22
8スレッド11.6222.99512.183.88

Core2Duo E6320(1.86GHz) Conroe

CPUFPUSSEC++速度比(FPU/SSE)
1スレッド35.759.43837.1093.788
2スレッド17.9844.7518.6713.786
4スレッド17.9534.7518.5943.776
8スレッド18.114.76618.6413.800

Pentium4 641(3.2GHz) Cedar Mill

CPUFPUSSESSE2速度比(FPU/SSE)
1スレッド50.6411.62519.8754.356
2スレッド27.0787.37514.3753.687
4スレッド26.9387.42214.4383.629
8スレッド26.8287.3914.4063.630

SSE版のソースコード


//	SSEを使用し水平4ピクセルを同時フラクタル計算を実行

void mandel_draw_sse(double a1,double b1,double a2,double b2,int sx,int sy,BYTE* pBits){
	float amax=(float)a2;
	float amin=(float)a1;
	int scrx=sx;
	float bmax=(float)b2;
	float bmin=(float)b1;
	int scry=sy;
	BYTE* p=pBits;
	const float lim=4.0;
	const unsigned B_MASK=0x0000c0;
	const unsigned B8_MASK=0x0000e0;
	const unsigned B32_MASK=0x0000f8;
	const unsigned CONST1=1;

	__m128 an;
	__m128 astep;
	__m128 bn;
	__m128 bstep;


	_asm{
		mov		eax,p
		mov		edi,scry
		mov		esi,scrx
		movss	xmm1,amax
		movss	xmm0,amin
		subss	xmm1,xmm0
		cvtsi2ss xmm2,esi

		divss	xmm1,xmm2	;	astep

		shufps	xmm0,xmm0,0x34 ; 3<-0 2<-2 1<-1 0<-0

		addss	xmm0,xmm1
		shufps	xmm0,xmm0,0xc4 ; 3<-3 2<-0 1<-1 0<-0
		
		addss	xmm0,xmm1
		shufps	xmm0,xmm0,0xe0 ; 3<-3 2<-2 1<-0 0<-0

		addss	xmm0,xmm1

		shufps	xmm0,xmm0,0x1b ; 3<-0 2<-1 1<-2 0<-3
		shufps	xmm1,xmm1,0	;	

		movaps	an,xmm0
		addps	xmm1,xmm1
		addps	xmm1,xmm1
		movaps	astep,xmm1


		movss	xmm3,bmin
		movss	xmm2,bmax
		subss	xmm3,xmm2
		cvtsi2ss xmm4,edi

		divss	xmm3,xmm4	;	bstep

		shufps	xmm2,xmm2,0x34 ; 3<-0 2<-2 1<-1 0<-0

		addss	xmm2,xmm3
		shufps	xmm2,xmm2,0xc4 ; 3<-3 2<-0 1<-1 0<-0
		
		addss	xmm2,xmm3
		shufps	xmm2,xmm2,0xe0 ; 3<-3 2<-2 1<-0 0<-0

		addss	xmm2,xmm3

		shufps	xmm2,xmm2,0x1b ; 3<-0 2<-1 1<-2 0<-3
		shufps	xmm3,xmm3,0	;	

		movaps	bn,xmm2
		movaps	bstep,xmm3

y_loop:
		mov		esi,scrx
		shr		esi,1
		shr		esi,1
		movups	xmm0,an
x_loop:
		movss	xmm7,lim
		shufps	xmm7,xmm7,0

		xorps	xmm4,xmm4		; x=0
		xorps	xmm5,xmm5		; y=0
		xorpd	xmm1,xmm1		; count
		mov		ecx,loop_n_max
LOOP_L1:
		movaps	xmm6,xmm4
		mulps	xmm6,xmm5	; x*y
		addps	xmm6,xmm6	; 2*x*y
		subps	xmm6,xmm2	; zy=2*x*y-b

		mulps	xmm4,xmm4		; x2=x*x
		mulps	xmm5,xmm5		; y2=y*y
		movaps	xmm3,xmm4
		subps	xmm4,xmm5	; x2-y2
		subps	xmm4,xmm0	; x=zx=x2-y2-a
		addps	xmm3,xmm5	; x2+y2
		movaps	xmm5,xmm6	; y=zy
		cmpltps	xmm3,xmm7	; x2+y2<4 真 1 偽 0
		pmovmskb edx,xmm3	;	各バイトの最上位ビットをedxにコピー
		test	edx,edx		;	4ピクセルがともにlimを超えた場合ループを抜ける
		jz	LOOP_L1_EXIT

		movd	xmm6,CONST1
		pshufd	xmm6,xmm6,0
		pand	xmm3,xmm6
		paddd	xmm1,xmm3	; 前の比較命令が真の時カウントされる
		loop	LOOP_L1
LOOP_L1_EXIT:

;	RR RRRG GGGGB BBBB->RRRR R000 GGGG G000 BBBB B000 32768色を32bitカラーにマッピング

		movdqa	xmm5,xmm1	;	  00RR RRRB BBBB
		pslld	xmm1,3		;   R RRRR BBBB B000
		movdqa	xmm4,xmm1
		movd	xmm7,B32_MASK
		shufps	xmm7,xmm7,0
		pand	xmm1,xmm7	; 青
							; 000G GGGG 0000 0000
		pslld	xmm4,3		; GGGG G000 0000 0000
		movdqa	xmm5,xmm4
		pslldq	xmm7,1
		pand	xmm4,xmm7	; 緑
		por		xmm1,xmm4
							; 000R RRRR 0000 0000 0000 0000
		pslld	xmm5,3		; RRRR R000 0000 0000 0000 0000
		pslldq	xmm7,1
		pand	xmm5,xmm7	; 赤
		por		xmm1,xmm5
		movups	[eax],xmm1
		add		eax,16
		movaps	xmm1,astep
		addps	xmm0,xmm1	;an+=astep
		
		dec		esi
		jnz		x_loop

		movups	xmm3,bstep
		addps	xmm2,xmm3
		dec		edi
		jnz		y_loop
	}

}

C++版のソースコード

void mandel_draw_c(double a1,double b1,double a2,double b2,int sx,int sy,BYTE* pBits){
	int x0=sx;
	int y0=sy;
	double a_min=a1;
	double a_max=a2;
	double b_min=b1;
	double b_max=b2;
	double a_step=(a_max-a_min)/x0;
	double b_step=(b_max-b_min)/y0;
	BYTE* top=pBits;
	double b=b_max;
	while(y0--){
		double a=a_min;
		x0=sx;
		while(x0--){
			double x=0;
			double y=0;
			unsigned int c=0;
			for(c=0 ; c < ::loop_n_max ; c++){
				double x2=x*x;
				double y2=y*y;
				double zx=x2-y2-a;
				double zy=2*x*y-b;
				x=zx;
				y=zy;
				if(x2+y2>= ::LOOP_MAX)
					break;
			}
			unsigned cr,cg,cb;
			switch(color_max){
			case 32768:	//	0rrr rrgg gggb bbbb
				cr=(c<<3) & 0xf8;
				cg=(c>>2) & 0xf8;
				cb=(c>>6) & 0xf8;
				c=RGB(cr,cg,cb);
				break;
			case 4096:	//	 rrrr gggg bbbb
				cr=(c<<4) & 0xf0;
				cg=c & 0xf0;
				cb=(c>>4) & 0xf0;
				c=RGB(cr,cg,cb);
				break;
			case 512:	//	r rrgg gbbb
				cr=(c<<5) & 0xe0;
				cg=(c<<2) & 0xe0;
				cb=(c>>1) & 0xe0;
				c=RGB(cr,cg,cb);
				break;
			case 64:	//	rr ggbb
				cr=(c<<2) & 0xc0;
				cg=(c<<4) & 0xc0;
				cb=(c<<6) & 0xc0;
				c=RGB(cr,cg,cb);
				break;
			}
			INT32* i32=(INT32*)pBits;
			*i32=c;
			pBits+=sizeof(INT32)/sizeof(pBits[0]);
			a+=a_step;
		}
		b-=b_step;
	}
}

色の割り付けのバグ H24.5.6

64色の場合、赤色が描画に反映されないことを発見した。すなわち実際は、16色表示となっていた。
色は、RGB形式で割り付けているため、大半がループの回数が少ない場合、特定の色に偏り面白みがない。
色の割り付けについては、再度見直し予定である。

コンパイラでのSSE命令 H24.5.6

アセンブラでFPUを使った場合とC++で記述し、コンパイラでSSE命令を吐き出させた場合で速度を比較するとほぼ同等でした。

Version 1.00 H17.12.23

主要計算ルーチンにインラインアセンブラを使用しFPUを酷使した、マンデルブロ描画プログラムを作成しました。

H17.04.10 公開
H17.04.19 描画をDIB上にするように変更。ファイルへ保存できるように変更。

特徴

 FPUをアセンブラレベルで使用することにより高速化を果たしている。

 画面上でマウスにより任意の範囲を拡大したり、中心点を移動することが可能。

 ディスクトップサイズにとらわれず大きな画像を作成可能。8192*8192の画像が作成できました。

 画像をクリップボードへコピーできる。

 BMP形式で保存できる。

 マルチモニターが使える場合は、その大きさに合わせて画像を作成したり、ウィンドウの大きさをあわせることが可能。

概要

  マンデルブロについて

  Zn+1=Zn2+C

 Z= x+yiC=a+biとした場合でZ=Z^2+C が成り立つ場合のxとyを求めます。

 xn+1+yn+1i=(xn+yni)^2+a+bi → xn+1+yn+1i=xn^2+2*xn*yni-yn^2+a+bi

 実数: xn+1=xn^2-yn^2+a

 虚数: yn+1=2*xn*yn+b

 

この式を簡単に解けないためx0=0,y0=0からスタートして近似していいきます。このときの近似回数をその点の色とします。ただし、Zの絶対値√(x^2+y^2)が2を超えた場合、発散して近時できないので打ち切りとし黒とします。また、近似回数の上限値を超えた場合、黒とします。

これらの計算を画面の横方向X座標をaとし縦方向をY座標をbとしてそれぞれの色を求めてます。

下記は原始的なプログラムです。
void draw(HDC hdc,double x0,double y0){
	double a_min=-0.7;
	double a_max=1.5;
	double b_min=-1.5;
	double b_max=1.5;
	double a_step=(a_max-a_min)/x0;
	double b_step=(b_max-b_min)/y0;
	int wx,wy;
	wx=
	 0;for(doublea=a_min;a<=a_max;a+=a_step){
		wy=
		 0;for(doubleb=b_min;b<=b_max;b+=b_step){
			double x=0;
			double y=0;
			int c=
			0;for(c=0;c<=511;c++){
				double x2=x*x;
				double y2=y*y;
				double zx=x2-y2-a;
				double zy=2*x*y-b;
				x=zx;
				y=zy;
				if(x2+y2>=4)
					break;
			}
			if(c==512){
				c=0;
				SetPixel(hdc,wx,wy,0);
			}else{
				SetPixel(hdc,wx,wy,color_map512(c));
			}
			++wy;
		}
		++wx;
	}
}
 

本プログラムでは、作成したい画像サイズに合わせたバッファをメモリ上に確保し、上記のC++のコードをアセンブラでコーティングされたルーチンにてメモリ上に描画します。

その後、表示の更新が生じた場合に、絶えずウィンドサイズに作成した画像全体が表示されるように拡大縮小して表示します。

メモリ上では32bitカラーで扱っており、8192*8192程度の大きさのサイズが限界でした。これを16bitにすればもっと大きな画像も作成できるでしょう。

アセンブラで作成したルーチンは内部でグローバル変数を変更せず、しかも内部で関数等を呼び出していないため、HT対応のPentium4やXeonのDualにあわせてスレッド数を増やすこともできるでしょう。

 

メニュー

名前をつけて保存 画像をbmp形式でファイルに保存する。
終了 本プログラムを終了する。

 

コピー クリップボードへ画像をコピーする。

 

前に戻る 直前の画像を表示する
次に進む 直後の画像を表示する
反復回数 計算の打ち切り回数を指定
色数 収束回数を何色に割り当てるか指定
フラクタル座標設定 表示するフラクタル座標範囲を数字で指定
窓ズーム 表示画面上で拡大する領域を指定する。
移動 表示画面上でどこを中心にするか指定
ズームアウト 表示画面を0.5倍にする。
イメージサイズ 任意 任意のイメージサイズの画像に設定する
イメージサイズ ディスクトップの大きさの画像に設定する。マルチモニタの場合プライマリモニターの大きさとなる。
イメージサイズ マルチモニタをサポートしている場合に表示される。全マルチモニターの合成サイズの大きさの画像に設定する。
マルチモニター全体で最大化 マルチモニタをサポートしている場合に表示される。全マルチモニターの合成サイズの大きさにウィンドウサイズをあわせる。

 

プログラムはVisual C++ 5.0で作成されています。Windows NT 4.0 、Windows 2000、Windows XPで動作確認しました。

当初Visual C++ 5.0のインラインアセンブラで記述していましたが、nasm用に変更しました。かなり文法が異なっているように思いました。ちなみに800*600の画像サイズで -1.333,-1.000 1.333,1.000の領域 反復回数の上限を32768とした場合の計算時間は、下記のとおりです。ウィルスバスターやLAN等につながった状態なのであまり正確ではありませんが

 

Thknkpad240X PentiumⅢ 500MHz RAM 192MBytes HDD 10GB  Windows 2000 Professional  224秒 Pentium4比で考えれば意外に検討しているような気がする。

Pentium4 3.2G(Prescot Dステップ Socket 478)  RAM 1GBytes(デュアルチャンネル) HDD 120GB Windows XP Professional 51秒

Pentium2 350MHz(Deschutes) RAM 128MBytes HDD 5GB Windows NT 4.0 Server 303秒

Pentium M 1.6GHz RAM 256MB Windows 2000 Professional 50秒
Pentium4を上回るスコア、Pentium4のFPUは1/2のクロックで動作している。

Athlon64 3000+(Socket 939) RAM 1GHz Windows 2000 Professional 41秒
Pentium 4 を上回るスコア。伝統的にFPUが強いのが裏付けられた。

Version 1.01 H18.05.07

ハイパースレッドの威力を試したくてアセンブラで記述された関数を2スレッド以上起動できるように改造した。
スレッド数は、表示メニューから選びます。

Pentium IV 3.2GHz(Prescot Socket 478)で2スレッドにすると51秒が26秒にスピードアップした。スレッド数増加によるオーバーヘッドは8スレッド程度ではPentium IV、Athlon64 3000+では見られなかった。

ATOM N280での実行速度 H21.5.31

ATOM N280(1.66GHz)で実行したところ 1スレッドで193秒、2スレッドで109秒であった。いずれにしてもFPUは今後、互換性のためだけに使われる運命のためあまり比較する意味はない。

実行速度 2014.01.19

i7-3820とi7-2600では同じ4コア8スレッドでコアの世代もSandy Bridgeである。実行速度を比べるとi7-3820では倍ほどの速度が出ている。ためしにi7-3820をクワッドチャンネルからデュアルチャンネル更にシングルチャンネルに変更しても速度は変わらなかった。キャッシュの違いであろうか。
LynnfieldやHaswellやSandy Bridgeともに4コアの場合2スレッドから4スレッドでの速度の伸びが少ないが8スレッドにすると速くなる。4コアでHT無でも同様である。2コアでHTの場合は8スレッド時の伸びが悪くなる。

CPU clock  1スレッド 2スレッド 4スレッド 8スレッド L2 L3 メモリ
 i5-3230M (Ivy Bridge)  2.6GHz 25 12  11  10 256k*2 3MB
 i7-3770 (Ivy Bridge)  3.4GHz 17 8   7   5 256k*4 8MB デュアルチャンネルPC3-12800 11-11-11-28(800MHz)
 i7-870 (Lannfield)  2.9GHz 21 10   9   6 256k*4 8MB デュアルチャンネルメモリPC3-10700 9-9-9-24(667MHz)
 i7-860 (Lannfield)  2.8GHz 19 9   8   7 256k*4 8MB デュアルチャンネルメモリPC3-10700 9-9-9-24(667MHz)
 i7-4770 (Haswell)  3.4GHz 17 9   8   5 256k*4 8MB シングルチャンネルメモリPC3-12800 11-11-11-28(800MHz)
 i7-3820 (Sandy Bridge-E)  3.6GHz 10(Turbo Boost 4.2GHz) 5(Turbo Boost 4.2GHz)   4(Turbo Boost 4.2GHz)   3(Turbo Boost 4.2GHz) 256k*4 10MB クワッドチャンネルメモリPC3-12800 11-11-11-28(800MHz)
 i7-2600 (Sandy Bridge)   3.4GHz 17 9   8   6 256k*4 8MB シングルチャンネルメモリ PC3-10700 9-9-9-24(667MHz)
 i7-2600 (Sandy Bridge)   3.4GHz 17 9   7   5 256k*4 8MB デュアルチャンネルメモリ PC3-10700*2(667MHz)
 i5-2500 3.3GHz 2.66GHz (Sandy Bridge)   3.3GHz(Turbo Boost on)  18(25%) 10(50%)   8(50%)   5(100%) 256k*4 6MB デュアルチャンネルメモリPC-10600 CL9(667MHz)
 Core i3-2100 (Sandy Bridge)   3.1GHz  21 10  10  8 256k*2 3MB シングルチャンネルメモリPC-10600 9-9-9-24(667MHz)
 i3-370M (Arrandale)  2.4GHz  26 14  13  13  256kB*2 3MB デュアルチャンネルメモリ PC3-8500 8-8-8-19
 i5-750 2.66GHz (Lynnfield)   2.8GHz(ターボブース時)  22 11  9  6  256kB*4 8MB デュアルチャンネルメモリ PC-10600(667MHz)
 Core2 Q8200 (Yorkfield)  2.33GHz 29 14  12   8 2M*2 デュアルチャンネルメモリ PC2-6400 6-6-6-18(400MHz)
 Core 2 Duo E6850(Conroe)  3.0GHz  23 13  12  12 4MB デュアルチャンネルメモリPC2-6400 5-5-5-16(400MHz)
 Core 2 Duo E4500 (Conroe)  2.2GHz(FSB 800MHZ)  30 15(100%)  16  15 2MB
 Core 2 Duo E4300 (Conroe)  1.8GHz  37 19  19  19 2MB デュアルチャンネルメモリPC2-5300 5-5-5-15(333MHz)
 Celeron 450 (Conroe-L)  2.2GHz 31 30  31  31 512k シングルチャンネルメモリ PC3-10700 6-6-6-15(400MHz)
 Pentium D 945 (Presler)  3.4GHz  26(50%) 13(100%)  14  14 2M*2 デュアルチャンネルメモリPC2-6400 6-6-6-18(400MHz)
 Pentium 4 641 (Cedar Mill)  3.2GHz  51 27  27  27 2M デュアルチャンネルメモリPC2-4300 4-4-4-12(266MHz)
 Pentium 4 531 (Prescott)  3.0GHz  54(50%) 29(100%)  29  29 1M シングルチャンネルメモリPC2-4300 4-4-4-12(266MHz)
 Pentium IV FSB800MHz (Prescott Socket478)  3.2GHz  51 26     1MB デュアルチャンネルメモリPC3200(400MHz)
 ATOM N280 FSB667MHz (Diamondville)  1.66GHz  193 109     512kB
 ATOM D525 (Pineview)  1.8GHz  134 69 58  41  1MB
 PentiumIII FSB100MHz (Coppermine)  500MHz  224       250kB
 PentiumII FSB100MHz (Deschutes)  350MHz  303       512kB
 Pentium M FSB400MHz (Banias)  1.6GHz  50       1MB
 Athlon64 3000+ (Venice)  1.8GHz  41       512kB デュアルチャンネルメモリPC3200(400MHz)

i5-750はクワッドコアでハイパースレッド無であるが、4スレッド以上もスピードが上がっている。4スレッド時のCPUの使用率は50%である。
同様にD525は2スレッドであるがハイパースレッドがあるため論理4CPUである。が8スレッドの方がスピードが速い。何らかの待ちにより100%性能を発揮できないため、スレッド数を増やすことによりさらに性能を増やすことができる。

ソースファイル、リソースファイル、実行ファイルダウンロード