2011年7月15日金曜日

7/15 map/unmap

メモリアクセスのAPIを変えて実験しているのだが、ヒープメモリ関係のバグが発生している。
原因はよくわかっていないが、最後にメモリをfreeしている場所でエラーが起きる。
大事な部分は全部mallocで確保しているので、ヒープは関係ない気がするのだが何なんだろう。

そもそもmap/unmapのAPIが正しく使えているのかが怪しいが、
検索してもそれらしい記述にたどりつくことができない。


先日まで取り組んでいたWindowサイズを変える実験も、
Windowサイズが大きくなると実行時間が減ってしまう部分があり、
実験結果の信憑性が疑われるのだが色々探しても原因やバグは突き止められなかった。
こちらもよくわからないが、とりあえず進捗が芳しくなく中間発表が恐ろしい。

2011年7月11日月曜日

7/11 実験の謎

ウィンドウサイズを4から1024まで2倍刻みで実験したのだが、
CPU/APUともほとんど実行速度に影響がなかった。
ウィンドウサイズを増やすと浮動小数計算量もメモリ転送量も2倍ずつ増えるので、
現在のデータ量では少なすぎるのだろうか。

ウィンドウサイズ1024、Ticker数640では、単純にウィンドウが占めるメモリ領域だけで、
配列長1024 x 2本 x 4Byte(float) x 640種類 = 5MBになる。到底L2キャッシュに収まる容量ではない。
シーケンシャルアクセスしか行われないので、CPU側への影響は薄いのかもしれない。
APU側のデータ転送時間にも全く影響のないところをみると、
ほとんどが呼出コストで、送受信自体はゴミのような時間しか食わないのか。
もしくはゼロコピーなるものがこっそり仕事しているのかも。

計算量もウィンドウサイズ4でTicker数1ならば掛け算と足し算が配列長分ずつ必要なので、
8回の浮動小数計算だが、ウィンドウサイズ1024でTicker数640ならば2 * 1024 * 640 = 1310720回になる。

CPUが1.6GHzなので、1サイクルは0.625ns。
浮動小数命令が今何サイクルかかるかよく知らないが、1サイクル以下はありえないので、
1で考えると1310720 x 0.625ns = 0.8192s。意外と短い。
計算量が少なすぎて、大した違いにならないのかもしれない。

もっと大規模データで実験しないといけないのだろうか。
実験の方向性がよくわからなくなってきた。

2011年6月26日日曜日

6/26 時間測定

今まで何も考えていなかったが、Windows環境での時間測定のやり方がわからない。
gettimeofdayが使えないだけでこれだけ苦労するとは・・・。

QueryPerformanceCounterやtimeGetTimeを使おうとしたのだが、
ぜんぜんうまくいかない・・・。

何が起こっているのかよくわからないが、今日中に終わらせるのは無理ということだけは確実だ。
諦めて明日誰かに聞く。

6/26

今までのバグの原因が判明した。
OpenCLカーネル内で、片方のスレッドがもう片方のスレッドの結果を上書きしていた模様。
これにより、実行の順番によって結果が変動していたようだ。
GPUのときに失敗しなかったのは、単純に運がよかっただけのようだ。

とにかく、これでバグは全部ないはずなのでベンチマークができる状態に仕上げなければ。

2011年6月24日金曜日

6/24 謎の挙動

スレッドの同期か何かの問題と思うのだが、CPU実行すると計算結果が2パターン現れる。
APUのほうでは十数回実行しても全く変化がなかった。何故だろう。

APU実行 正しい結果(計算の誤差は大きい模様)


CPU実行 正しい結果


CPU実行 誤った結果


この問題さえどうにかなれば、後は数十~数百スレッドで実行時間を測定すればよい。
先はまだまだが、どうにかなりそうにはなってきた。


bi(bargain index)に-0と-expがあるが、これはvwapとask_priceの関係によって式が2種類あるため。
どちらの分岐に入ったかを検知するために付与している。


APU(GPU)は演算器の実装が違うのか誤差が出やすい模様。
今後、この点にも注意する必要がありそう。

6/24 OpenCL Debug

とうとうOpenCLでVWAP計算が動作した。
しかしながら、まだシングルスレッドで一周のみの動作しかさせていないので、
複数スレッドで連続計算できるように改修が必要だ。
カーネル関数自体の動作は確認できたので、作業はだいぶ楽になった。

OpenCLのDebugではFermi以降のCUDAと同様kernel関数内部でのprintfが使える。
書式はC/C++と同様で、文字列なども難なく扱える。
表示が実際に行われるタイミングは非同期のようだが、同期を行えば確実に表示できる。
clWaitForEvents関数がそれで、第一引数に待ちイベント数、第二引数にイベント配列を渡す。
イベント配列はカーネル関数実行時やメモリ読み書き時に指定できるので、
カーネル関数実行時に設定したイベントをこの関数に渡してやればよい。

・OpenCL 1.1のKhronos公式のリファレンス
知りたい関数などを一発で検索できるため大変便利
http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/

2011年6月17日金曜日

6/17

OpenCLのカーネルビルド時のエラーの詳細を見るための関数があるようだ。

 clGetProgramBuildInfo(program, device_id, CL_PROGRAM_BUILD_LOG, sizeof(buffer), buffer, &len);

これで作業が少しは楽になりそう。

しかし、これを知ったのがBuild Errorを解決してからだった。ショック。
しかも、今度はNDRangeKernelの起動でエラーが。

先は長そうだ。