概要

任意の領域に対して単精度または倍精度浮動小数点でマンデルブロを描画します。
計算にはFPU、SSE、SSE2、AVX命令を使うことができます。

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

色数が多い領域を自動的に連続拡大する機能があります。
主要計算ルーチンにインラインアセンブラを使用しFPU、SSE、SSE2、AVXを使用しています。
同時計算スレッド数を指定できますのでマルチコアやハイパースレッドを有効に活用できます。
ディスクトップサイズにとらわれず大きな画像を作成可能。8192*8192の画像が作成できました。
画像をクリップボードへコピーできる。
BMP形式で保存可能。
Version 2.1からの改良点は以下の通りです。

古いパソコンを使う機会があったのでWindows 95で使用できるようにVisual C++ 97(5.0)でコンパイルできるようにコードを修正しました。MMX Pentium(Windows 95)で実行できました。
SSEで計算するときに色変換時にSSE2のコードが使われていたので、SSEのみで計算できるように修正しました。
SSE2をサポートしていないCeleron(Coppermine-128k)でSSE2命令が含まれる実行ファイルを実行するとエラーが起こらないことがわかりました。エラーは起こりませんが、正常動作はしません。

テスト環境

コンパイラと実行可能なOS及びCPU

Visual C++ 2013 Express 32bit マルチバイト/UNICODE

Windows XP以上 CPUが対応していれば FPU SSE SSE2 AVXを使用可能

Visual C++ 2008

Windows 2000以上 CPUが対応していれば FPU SSE SSE2を使用可能

Visual C++ 2005

Windows 98以上 OS CPUが対応していればFPU SSEを使用可能

Visual C++ 97(5.0)

Windows 95以上 FPUのみ

動作確認環境

以下の環境で動作確認をしました。
HITACHI FLORA 270 PC-5NH02-YA5LA MMX Pentium 166MHz with Windows 95 Visual C++ 97で作成した32bit実行ファイル
HITACHI FLORA 270GX PC7NW1-GDE27H420Celeron 600MHz with Windows 98 SE Visual C++ 97で作成した32bit実行ファイル
HITACHI FLORA 270GX PC7NW1-GDE27H420Celeron 600MHz with Windows 2000 Visual C++ 2005で作成した32bit実行ファイル
HP ProBook5220m Core i3-M370 with Windows XP 32bit Visual C++ 2013で作成した32bit実行ファイル
自作PC Core i7-3820 with VirtualBox上のWindows Vista 32bit Visual C++ 2013で作成した32bit実行ファイル
自作PC Core i7-3820 with Windows 7 64bit Visual C++ 2013で作成した32bit/64bit実行ファイル
HP ProBook5220m Core i3-M370 with Windows 8.1 64bit Visual C++ 2013で作成した32bit実行ファイル
HP ProBook5220m Core i3-M370 with Windows 10 64bit Visual C++ 2013で作成した32bit実行ファイル

マンデルブロについて

b 虚数 amin,bmin a 実数 amax,bmax 0,0 x0 y0 画面 SVGの代替画像



とした場合で

が成り立つ場合のを求めます。


実数:
虚数:
この式を簡単に解けないためからスタートして近似していきます。
このときの近似回数をその点の色とします。ただし、Zの絶対値が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;
	}
}

メニュー

ファイルメニュー

名前をつけて保存

画像をbmp形式でファイルに保存する。

終了

本プログラムを終了する。

編集メニュー

コピー

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

表示メニュー

前に戻る

直前の画像を表示する

次に進む

直後の画像を表示する

窓ズーム

表示画面上で拡大する領域を指定する。

移動

表示画面上でどこを中心にするか指定

ズームアウト

表示画面を0.5倍にする。

オプション

計算方法、画像サイズ等を指定するダイアログボックスを表示します。

左上座標・右下座標
計算するフラクタル座標の範囲を指定します。
画像サイズ
作成するフラクタル画像のサイズを指定します。
色数
計算の反復回数を指定します。
スレッド数
同時に起動するスレッド数を指定します。
FPU SSE C++ SSE SSE2 AVX
使用する拡張命令を指定します。
初期値
フラクタルの計算諸元を以下の値に設定します。
初期座標:-1.33333,-1.00000 1.33333,1.00000
画素数:800*600
反復数: 32768回

自動拡大


自動拡大は現在表示されている領域に対して色数が多い領域(16分割)を拡大し画像を保存するようにしました。拡大は、指定した回数分、自動的に行います。
自動拡大された画像を確認すれば、マンデルブロのお気に入りの領域を探すのが楽になります。
自動拡大された画像はカレントフォルダーにimage日時という名前のフォルダーの中のimageフォルダーに保存されます。
自動拡大した場合に作成された画像ファイルをエクスプローラーでサムネイル表示したものを以下に示します。

座標及び色数等と画像のサムネイルを表示するためのindex.htmlファイルが作成されます。
以下に自動拡大で作成される画像の一覧のリンクを示します。
index.html

各CPUでの実行速度

自動拡大の実行速度

初期座標:-1.33333,-1.00000 1.33333,1.00000
画素数:800*600
最大画像数: 100回
最大ループ: 32768回
名称 スレッド FPU 倍精度C++ 倍精度SSE 単精度SSE2 倍精度AVX 単精度AVX 倍精度
Celeron 600MHz(Coppermine)12274.32080.1115011.356
Pentium(R) 4 CPU 3.20GHz2401.2970387.2970794.281196.3910
Celeron(R) CPU G1620 @ 2.70GHz2189.293190.451292.90479.895
Celeron(R) CPU G1840 @ 2.80GHz2191.840168.955296.79676.060
Core(TM) i3-M370 @ 2.40GHz4140.0704120.047228.84563.110
Core(TM) i7 CPU 870 @ 2.93GHz852.16760.575 89.84024.476
Core(TM) i7-3820 CPU @ 3.60GHz837.18137.18376.25818.30730.88010.562
Core(TM) i7-3770 CPU @ 3.40GHz842.07340.71075.76921.48134.50813.168
Atom Z37754657.435459.341702.252408.438
AMD A4-5300 3.4GHz2253.094169.127345.93091.557232.23876.721
Core(TM) i7-4790 4.0GHz(Haswell Refresh)871.96738.98572.82120.65441.02816.053
Core(TM) i7-2600(Sandy Bridge) 3.8GHz849.4347.17583.39824.88240.48214.992
Core(TM) i5-4440(Haswell) 3.1GHz497.12186.136142.05239.89565.24223.359
単精度と倍精度では精度が異なるため計算結果に相違がでて、スタートが同じ座標でも拡大が進むにつれ違う領域を計算することになる。このケースでは、倍精度の時、計算負荷が少ない領域が選択されている。

各CPUでの実行速度

各CPUの計算時間(単位は秒)をシングルスレッドとCPUのコア数、サポートしている最大スレッド数それぞれ計測してみた。
各実行速度は、CPUへのスレッド割り付けは固定しているが、スレッドに*がついている場合は、CPUの割り付けは固定していない速度を表している。

Version 2.3での実行速度

名称スレッドFPU 倍精度C++ 倍精度SSE 単精度SSE2 倍精度AVX 単精度AVX 倍精度
MMX Pentium 166MHz(Tillamook)1871.882615.39
Pentium 2 450MHz(Deschutes)1213.835414.276
Celeron 600MHz(Coppermine)1163.41591.6049.431
Celeron 667MHz(Coppermine)1157.8571.17未測定未測定
Celeron 2.0GMHz(Northwood)170.31369.48514.5027.203
Atom D2701(Cedarview) 2.13GHz 10W1110.3256.20722.95483.115
Atom D2701(Cedarview) 2.13GHz 10W446.70624.0019.64237.189
Pentium4 641(Cedar Mill) 3.2GHz 86W*150.38148.91211.83019.83
Pentium4 641(Cedar Mill) 3.2GHz 86W*226.11225.0507.37614.283
Celeron 430(Conroe-L) 1.8GHz 35W140.0648. 3299.92223.728
Celeron 925(Penryn) 2.3GHz 35W129.46535.597.20715.803
Core2Duo E7500(Wolfdale) 2.93GHz 65W*122.74527.3005.81812.043
Core2Duo E7500(Wolfdale) 2.93GHz 65W*211.43413.6972.9646.069
i3-370M(Arrandale) 2.4GHz 35W1 26.125 26.094 6.250 12.578
i3-370M(Arrandale) 2.4GHz 35W4 11.625 10.984 2.750 5.500
Celeron G1620 2.7GHz 55W*1 24.174 22.517 5.438 10.376
Celeron G1620 2.7GHz 55W*2 12.000 11.188 2.703 5.219
Celeron G1840 2.8GHz 53W1 23.798 20.860 5.094 10.109
Celeron G1840 2.8GHz 53W2 12.160 10.611 2.593 5.110
i7-2600(Sandy Bridge) 3.8GHz 95W1 16.754 16.474 3.947 7.754 1.919 3.728
i7-2600(Sandy Bridge) 3.8GHz 95W8 4.586 4.508 1.108 2.090 0.546 1.030
i7-3820(Sandy Bridge-E) 4.2GHz 130W1 15.05 14.960 3.523 6.949 1.728 3.346
i7-3820(Sandy Bridge-E) 4.2GHz 130W8 3.956 3.807 0.930 1.840 0.432 0.890
i7-4790(Haswell Refresh) 4.0GHz 84W1 16.739 14.664 3.650 7.129 2.262 4.368
i7-4790(Haswell Refresh) 4.0GHz 84W8 4.742 3.946 1.077 1.919 1.108 1.185
Core(TM) M-5Y71 1.2GHz 4.5W123.34415.5794.3598.1882.3444.562
Core(TM) M-5Y71 1.2GHz 4.5W213.6888.7352.4854.7031.3752.594
Core(TM) M-5Y71 1.2GHz 4.5W411.5787.4852.5474.0781.1712.343
AMD A4-5300 65W1 26.286 19.203 5.569 10.826 3.026 6.068
AMD A4-5300 65W2 16.411 10.374 3.026 5.679 2.652 5.975
Atom Z3775 1.46GHz(Bay Trail-T)177.90632.46910.93833.688
Atom Z3775 1.46GHz(Bay Trail-T)432.86013.7354.59414.234
i5-4440 3.1GHz(Haswell) 3.1GHz 84W120.31117.7684.4008.5962.4814.774
i5-4440 3.1GHz(Haswell) 3.1GHz 84W48.5807.5041.8403.6351.0452.012
i5-4440 3.1GHz(Haswell) 3.1GHz 84W85.6474.9611.2632.3870.7021.342

各CPUの概要

CPUクロック開発コードコア数HTL1 instL1 dataL2L3ラインサイズメモリ帯域
MMX Pentium166MHzTillamook1無効16kB(4way)16kB(4way)32バス66MHz*8=533MB/s
Pentium 2450MHzDeschutes1無効16kB(4way)16kB(4way)512kB(4way)32メモリ100MHz*8=800MB/s
Celeron600MHzCoppermine1無効16kB(4way)16kB(4way)128kB(4way)32メモリ100MHz*8=800MB/s
Celeron667MHzCoppermine1無効16kB(4way)16kB(4way)128kB(4way)32メモリ100MHz*8=800MB/s
Celeron2.0GHzNorthwood1無効12kuμops(8way)8kB(4way)128kB(2way)64FSB400MHz DDR266デュアル 4.3GB/s
Atom D27012.13GHzCedarview2有効32kB*2(8way)24kB*2(6way)512kB*2(8way)64DDR3-1066 17.1GB/s
Pentium4 6413.2GHzCedar Mill1有効12kuμops(8way)16kB(8way)2MB(8way)64DDR2-533 6.4B/s
Celeron 4301.8GHzConroe-L1無効32kB(8way)32kB (8way)512kB(2way)64DDR2-800 6.4GB/s
Celeron 9252.3GHzPenryn1無効32kB(8way)32kB (8way)1MB(4way)64DDR3-1333 10.7GB/s
Core2Duo2.93GHzWolfdale2無効32k*2(8way)32k*2(8way)3MB(12way)64FSB1066MHz DDR2-800 12GB/s
Core i3-370M2.4GHzArrandale2有効32kB*2(4way)32kB*2(8way)256kB*2(8way)3MB(12way)64DDR3-1066 17.1GB/s
Celeron G16202.7GHzIvy Bridge2無効32KB*2(8way)32KB*2(8way)256kB*2(8way)2M(8way)64DDR3-1600 12.8GB/s
Celeron G18402.8GHzHaswell2無効32KB*2(8way)32KB*2(8way)256kB*2(8way)2M(8way)64DDR3-1333 21GB/s
Core i7-26003.4GHz(3.8GHz)Sandy Bridge4有効32k*4(8way)32k*4(8way)256k*4(8way)8M(16way)64DDR3-1333 21GB/s
Core i7-38203.6GHz(4.2GHz)Sandy Bridge-E4有効32KB*4(8way)32KB*4(8way)256kB*4(8way)10M(20way)64DDR3-1600 51.2GB/s
Core i7-47903.6GHz(4.0GHz)Haswell Refresh4有効32KB*4(8way)32KB*4(8way)256kB*4(8way)8M(16way)64DDR3-1600 25.6GB/s
AMD A4-5300 3.4GHz(3.6GHz) Trinity 2 無効 64kB(2way)16kB(4Way)*21024kB(16Way)64DDR3-1600 12.8GB/s
Core(TM) M-5Y711.2GHz(2.9GHz)Broadwell-Y2有効32kB*2(8Way)32kB*2(8Way)256kB*2(8Way)4MB(16Way)64LPDDR3-1600 25.6GB/s
Atom Z37751.46GHzBay Trail-T4無効32kB*4(8Way)24kB*4(6Way)1MB*2(16Way)64LPDDR3-1066 8.533GB/s
i5-44403.1GHz (3.3GHz)Haswell4無効32KB*4(8way)32KB*4(8way)256kB*4(8Way)6M(12way)64DDR3-1600 25.6GB/s

変更経歴

A4-5300の実行速度を追加 2016/01/23

旧バージョン

マンデルブロ描画プログラムVersion2.1 2014/11/25
マンデルブロ描画プログラム 2014/09/27

プログラムソースの概要

mandel23.cpp

_tWinMain

GdiplusStartupによりGDI+を初期化します。
GetEncoderClsidによりjpeg用のエンコーダーを取得します。
ウィンドウを起動します。
GdiplusShutdownによりGDI+を開放します。

WndProc

ウィンドウプロシージャーです。
WM_CREATE
ウィンドウの初期化時に呼び出されます。
ステータスバーの作成をします。
画面のバッファであるメモリコンテキストデバイスの作成及び計算の初期値を設定し、初期値に基づくマンデルブローを描画します。
WM_SIZE
ウィンドウの大きさが変更されたとき呼び出されます。
ステータスバーの位置を変更します。
WM_MOUSEMOVE
マウスカーソルが移動されたときに呼び出されます。
移動中又は窓ズームに応じた処理を行います。
WM_LBUTTONDOWN
マウスの左ボタンが押された時に呼び出されます。
移動中又は窓ズームに応じた処理を行います。
WM_LBUTTONUP
マウスの左ボタンが離された時に呼び出されます。
移動中又は窓ズームに応じた処理を行います。
WM_COMMAND
IDM_ALLSET
マンデルブロの座標範囲、画像の大きさ、スレッド数、拡張命令を設定するダイアログボックスを呼び出します。
IDM_SAVE2
ファイルを選択するコモンダイアログボックスを表示しファイル名を取得します。
save_bmpを呼び出し画像をBMP形式で保存します。
IDM_EXIT
プログラムを終了させます。
IDM_BACK
前回の座標で表示します。
IDM_FORU
過去の表示から1つ現在に向かって表示を進めます。
IDM_ZOOM_OUT
ズームアウトします。
IDM_WIN_ZOOM
窓ズームを開始します。
IDM_WIN_MOVE
表示を移動させます。
IDM_AUTO
自動拡大する回数を入力するダイアログボックスを表示し、回数を取得します。
日時を取得し画像を保存するフォルダーを作成します。(CreateDirectory API)
画像のサムネイルを表示するindex.htmlファイルをオープンします。 msg_chk関数よりWindowsメッセージをチェックしWM_PATIN及びWM_KEYDOWNでVK_ESCAPEのメッセージを処理します。
ESCキーが押されている場合(VK_ESCAPE)は自動拡大を終了させます。
現在の座標でマンデルブローを描画します。
color_chkメンバ関数により現在表示されている座標を16分割しそれぞれの使用されている色数を取得します。
16分割のうち最大の色数の領域を取得します。
色数が4以上の場合は、画像をそのままbmpへ保存(save_bmp)、画像を縮小してjpegへ保存(SaveBitmap)、画像へのリンクを作成します。
現在の画像の領域ごとの色数等をMANDEL_PARSEクラスに保存し、MANDEL_TREEクラスに登録します。
色数が4未満又は計算に使用している浮動小数点の型から決まる座標の横幅より小さい場合は、分割された領域へ拡大することはできないと判断し、現在の領域の分割する前の領域に戻り、その領域の分割された領域で色数が最大でかつ描画されたことがない領域へ移動します。
色数が4以上の場合は、分割された領域で一番色数が大きい領域の座標を計算し、前述のmsg_chk関数へジャンプします。
WM_DESTORY
メモリデバイスコンテキストを開放し、ウィンドウを終了させます。
WM_CLOSE
ウィンドウ終了時に呼び出されます。
WM_PAINT
ウィンドウの表示を更新する必要がある場合呼び出されます。
マンデルブロの計算結果は各スレッド用のメモリからウィンドウのバッファ部にコピーされウィンドウに表示されます。
再計算の必要がない場合は、メモリデバイスコンテキスト(バッファ)からウィンドウへコピーします。

SetDlgPro

マンデルブロの座標範囲、画像の大きさ、スレッド数、拡張命令を設定します。

AutoSetDlgProc

フラクタル自動拡大する回数を取得するダイアログボックスを表示します。

mem_free

各スレッドに参照されるマンデルブロのパラメータを保存しているメモリを解放します。

save_bmp

bitmapをbmpファイルへ保存する

SaveBitmap

bitmapを拡大縮小してエンコーダーで指定されるフォーマットのファイルとして保存します。
保存には、GDI+を使用しており、あらかじめエンコーダーを取得しておく必要があります。

GetEncoderClsid

GDI+で使用するエンコーダーの取得します。
引数に与える文字列によって、jpeg,png等の種類を指定できます。

msg_chk

時間のかかる処理にメッセージ処理の機会を与えます。
メッセージをチェックし、WM_PAINTの場合は、メッセージを実行します。
WM_KEWYDOWNの場合はESCキーであるかチェックし、ESCキーの場合はtrueを返します。
呼び出し側は、trueの場合、自動拡大を中止します。

GetWinRect

ウィンドウのクライアント領域の大きさを返します。

CreateStatus

ステータスバーを作成します。

status_bar_str

マウスにより画像の領域を選択中にステータスバーに表示する文字列を作成する

mandel_draw_current

指定された座標及び画像サイズのマンデルブロを作成します。
この関数では指定数のスレッドを作成(mandel_draw_child関数)し、マルチスレッドでマンデルブロの計算をします。 座標の縦方向を指定したスレッド数で分割して同時計算させている。

mandel_draw_child

選択されている拡張命令(FPU,SSE,AVX等)によりマンデルブロを計算する関数を呼び出します。

simd.cpp

IsWindowsVersionOrGreater

OSがAVXに対応しているか確認するために指定バージョン以上かどうかを返します。

IsWindows7SP1OrGreater

OSがAVXに対応しているか確認するためにWindows 7 Service Pack 1バージョン以上かどうかを返します。

mandel_draw_fpu2

FPUは1スレッドあたり、1ピクセルごとに計算する。
FPUレジスタは8個あるが、スタック構造なので、直接レジスタの場所を指定できず、例えばスタックトップとスタックトップからn個目といった指定の仕方をする。
オペランドの一方がスタックトップにある必要があるので、都合が悪い時はfxch命令でスタックトップとスタックトップからn個目の値を交換する。
レジスタに値をロードするとスタックにプッシュされる。スタックがあふれるとエラーが発生するので、スタックトップを破棄する必要がある。この場合、計算後に自動的に破棄する命令(fcomp等)を使うか、fincstp、fstp st(0)等を用いる。
Windowsの64bit版ではFPUを使わないことを奨励している。
Intel自身も高速化のしにくいFPUよりSIMDを使用することを奨励している。

mandel_draw_sse・mandel_draw_sse2

SSEは1スレッドあたり、水平方向4ピクセルを単精度で同時に計算、SSE2は水平方向2ピクセルを倍精度で同時に計算する。
座標等の初期値はスカラー命令(1個の浮動小数点を扱う命令)でXMMレジスタに取り込みシャッフル命令でXMMレジスタの各要素(8個又は4個)にコピーする。
以降パックド命令(複数のデータを同時に扱う命令)を使い計算をする。
式が4以上になったときのカウント値を各ピクセルごとに抽出する必要がある。この値は各ピクセルごとに異なる。
4以上がどうかをcmpltps,cmpltpdで比較する。4以上の場合対応する要素のビットが全部0になる。未満の場合はビットが1となる。
同時に扱っているピクセルが全部4以上になった場合をチェックするために、movmskps又はmovmskpd命令で各要素の最上位ビットをdxレジスタに転送している。dxレジスタに対してtestを命令を実行すると、ゼロフラグがセットされているときは各要素全部が4以上なので、ループを抜けることができる。
要素のビットをandでマスクし、4以上の場合は整数の0、未満の場合は1となるようにし、カウンタをadd命令で加算する。こうすれば4未満のピクセルはカウントされ、4以上のピクセルはカウントされないので、同時に扱っているピクセルのループ回数が同一にできSSE又はSSE2命令で記述が可能となる。

mandel_draw_avx・mandel_draw_avxd

AVXは1スレッドあたり、水平方向8ピクセルを単精度で同時に計算又はは水平方向4ピクセルを倍精度で同時に計算する。
AVXは浮動小数点に限りスカラー値をYMMレジスタの各要素にコピーすることができる。vbroadcastss,vbroadcastsd命令(AVX2では整数でも可能) 以降パックド命令(複数のデータを同時に扱う命令)を使い計算をする。
式が4以上になったときのカウント値を各ピクセルごとに抽出する必要がある。この値は各ピクセルごとに異なる。
4以上がどうかをvpcmpltps,pcmpltpdで比較する。4以上の場合対応する要素のビットが全部0になる。未満の場合はビットが1となる。
同時に扱っているピクセルが全部4以上になった場合をチェックするために、vpest命令を使います。この命令は2つの256bit値のandをとり、その結果に基づきゼロフラグ、キャリーフラグをセットします。ゼロフラグがセットされているときは各要素全部が4以上なので、ループを抜けることができる。
比較結果に基づきvmaskmovps,vmaskmovpd命令により各要素ごとに1をロードするかしないかを制御している。これにより比較結果により1又は0が設定されるので、カウンタをadd命令で加算する。こうすれば4未満のピクセルはカウントされ、4以上のピクセルはカウントされないので、同時に扱っているピクセルのループ回数が同一にできAVX命令で記述が可能となる。
なおAVXには整数を扱う命令が少ないので、浮動小数点でカウントをし、カウント後、vcvtps2dq,vcvtpd2dqで32bit整数に変換する。
AVX命令には整数を扱う命令が少ないので、YMMレジスタの上位下位を別々にSEE命令によりRGBに変換している。AVX2を用いれば高速に処理できるが、該当するCPUを持っていないのでAVXで記述している。

isAVX

CPUがAVX命令をサポートしているかどうかを返します。

color_count

色数を返す

color_chk

画像の領域ごとの色数をカウントする

hi_chk

一番色数の多い領域を返す

cpu.cpp cpu.h

基本的には、CPUの物理CPU数・ソケット数等を取得(32/64bit)のCPUクラスにスレッドの割り付け関数(cpu.h)を追加しています。ここでは追加部分のみ記載しております。

CPU::alloc_cpu

指定したスレッド数に対する論理CPU番号の配列を返します。
スレッド数がコア数以下の場合は、それぞれ異なるコアにスレッドを割り当てます。
スレッド数がコア数以上の場合は、異なるコアに優先して割り当てコア数が最大に達したらCPUのセカンドスレッドに割り当てます。

CPU::getWinCpu

指定したコアのスレッド(CPU)にスレッド(プログラム)を割り当てます。パッケージが複数ある場合は、パッケージ間で連続したコア番号があるとみなしで指定します。

ソースコードと実行ファイル

実行ファイルとソースファイルのダウンロード(mandel23.zip 210kByte)
ZIPファイルに含まれるファイル

mandel23.cpp
mandel23.exe		Visual C++ 2013でビルド Windows XP以上で実行可能
mandel23_0097.exe	Visual C++ 97(5.0)でビルド WIndows 95以上で実行可能
mandel23_2005.exe	Visual C++ 2005でビルド WIndows 98以上で実行可能
mandel.ico
mandel.rc
cpu.cpp
cpu.h
resource.h
simd.cpp
undervc2005.h