C#は電気羊の夢を見るか?(引っ越し中)

dtiブログが閉鎖とのことでhttp://tanocs.blog.fc2.com/へ引っ越します。

GPGPUの現状

結構とXNAでGPGPUをやりたい方が多いようで、
[XNA GPGPU]をキーにgoogleからの来訪者が多い。

そこで、まぁいいかと放ったらかしにしていた現状について話さざるをえない・・・。

というのも、じつは公開中のGPGPUのソースははっきり言って全然使いものにならない。
なぜならピクセルシェーダーを使ってるから。

ピクセルシェーダーはほとんど処理が並列化されないので、
GPGPUの利点を生かしきれない。と思う。
GPGPUとしてピクセルシェーダーは遅いと思っていた要因が別にある可能性があり、
厳密な計測や比較が出来ていないから断定はできない。

ただ、応用の基礎として読み取るには調度良いわかりやすさがあるので、
そのままにしているのだが、実際はそのままでは実用には耐えないと思われる。


GPGPUとして本格的に使用したい場合はバーテクスシェーダーを用いる必要がある。
バーテクスシェーダーを使うにはいくつかの”コツ”がいる。

そのコツは以下の通り
・VertexElementを自前で定義する
 色情報や法線情報として自分が計算したいと思っている大量のデータを
 バーテクスシェーダーに渡すようにする。
 その際、位置情報は出力するレンダーターゲットの座標を表すようにする。

 ちなみにその座標は左上が(-1,1,0),右下が(1,-1,0)として指定する。
 取り得る値の範囲が-1〜1で、何故かXとYが反転する点に注意が必要

例:1024 * 1024のレンダーターゲットの場合
   (1024, 1024) → (1, -1, 0)
   (512, 256) → (0, 0.5, 0)
   (256, 0) → (-0.5, 1, 0)
   

・頂点を点として描画する
 graphics.RenderState.FillMode = FillMode.Point;
 graphics.RenderState.PointSize = 1;
 上記のようにレンダーステートを点描画モードにしてやる。

 通常のGPGPUでは必要ないと思うけど、
 計算結果を3Dモデルで表示したいとかで、通常の描画に戻したいときは
 graphics.RenderState.FillMode = FillMode.Solid;
 とすればいい


具体的なソースの提示はいつかしたいと思っているが、
いかんせん、高速化の名目で現在作成中のプログラムに密結合しているので
引き剥がしてサンプル化するのに手間がかかってしまうのでとりあえずで勘弁して下さい。

このエントリーをはてなブックマークに追加
LINEで送る

GPGPUの高速化

今回の実装で高速化が程度できたっぽいので効果のあった方法をメモ


まず、以前より改善を続けていたtexture2d.getdata()は
もってくるテクスチャサイズは小さければ小さいほどよい。
少々計算が複雑になってもサイズを小さくするほうが効果がある。


そして意外と盲点だったのは、メモリの管理。
ループ内で呼び出している外部関数で巨大なメモリを使用している場合、
引数にrefキーワードを用いるだけで劇的な改善が見られた。

これに気を良くして、そんなに効果があるならと
newキーワードの対象となる配列の宣言を極力ループの外に放り出すと
それだけでかなり速度が改善された。


例:
for(int i = 0; i < src.length; i++){

int[] hoge = new src.getData();
}
上記ソースを
int[] hoge;

for(int i = 0; i < src.length; i++){
hoge = new src.getData();
}
とするだけ。

このsrc.getData()のサイズが数メガに及ぶような場合、メモリや可読性が許せば
高速化のためにグローバル化(メンバ化)してしまうのも良いかもしれない。


本来ローカル変数はスコープが外れると無効にはなるものの、
ガベージコレクタさんが動くまでは、事実上はメモリを使用してる。

いつ動くかよくわからないガベージコレクタさん。
気がつくと多くの未使用メモリが増えることが多いのではないだろうか。
そしてガベージコレクタさんのお仕事の量が大きくなると処理もそれなりに重くなるっぽい。

特に描画処理は最大で秒間に60回近く呼ばれている計算になり、
そいつをforで2重ループなんかしている日にゃ、なかなかときつい仕事になるわけだ。

上記の例のように露骨にnewされている場合は気が付きやすいけど、
関数の引数もメモリを食っているので注意が必要。


あくまで一例だが、私の場合、5万近くの要素数になる配列の宣言を
メンバ化して計算用関数の引数をref化した結果15fps→60fpsと劇的な改善が見られた。

ただ、ゲームクラスのメンバにモデルの頂点データがいるのは実に気持ちが悪い。
計算用のグローバルだと思おう・・・


ここの記事によるとtexture2dをフリップ化することで
GPUとCPUで並列処理が可能になるとのことで、
もう少し処理の高速化が必要になったら試してみたい。

実は今回結局MRTで2回テクスチャの取得処理を発行しているが、
テクスチャフリップの際は2パスへの変更が必要だろうなと思う。
このエントリーをはてなブックマークに追加
LINEで送る

小ネタ

■スタイリッシュ配列指定
 ※あくまでスタイリッシュであって、速度のことは知らない

a.First(); //a[0]
a.Last(); //a[a.Count - 1]

考察:
可読性は結構上がる。あとなんとなくカッコイイ。
しかしながら、メソッドであるため、戻り値がメモリにわざわざ置き直されるんじゃなかろうか?

そうすると、配列一つあたりのメモリ使用量が大きい場合、結構速度へ影響があるような気がする。
例えばa.First().ToString()とか言う感じで参照後のメソッドを呼び出すような場合、
顕著に現れる気がする。
もちろん、気がするだけで実証はしてない。


.Last()は速度への影響が少ないところにはぼちぼち使ってみたい。
.Firstは文字数的にも見た目的にも速度的にも微妙。
自身が長年 a[0] の表記に慣れ親しんでいるので、あまり使わない気がする。


■sortedリストのエラーメッセージ
しょぼいミスで『少なくとも 1 つのオブジェクトで icomparable を実装しなければなりません。』とか言うエラーが出たときの対処法。

SortedList.Max() はできないので SortedList.Last() とすること。
結果はよっぽど同じになるはず。


■迷った時は
SortedListかSortedDictionaryで迷った場合、
ランダムアクセスとキー指定の頻度が多ければSortedDictionary。
比較的単純なアクセスが多く速度がほしい時はSortedListが優秀。


■応急処置
現場とかでどうしてもソースをいじるのに
Visual C# 2008 Express Editionを使用する場合、
相手方が64Bitだったりすると、CPUの選択ができずに詰む。

これの対処のためにテキストエディタで
ソリューション(*.sln)とプロジェクトファイル(*.proj)を開き
[Any CPU][AnyCPU]を[x86]にすると対応できる上、
何故か構成マネージャが有効になる。
このエントリーをはてなブックマークに追加
LINEで送る

HDD復旧の結果発表

なんとか元に戻りました〜

超重要なデータのみはバックアップがありましたが、
やはり古かったり、取りこぼしがあったり、諦めきれないデータがいくつもありました。
本当にデータが復旧してよかったです。

しかしながら、今回は本当に運が良かったのだと思います。
通常であれば十分寿命を迎えていそうな使用年数にも関わらず死んでい無かった事。
メーカーによる”大規模な”不具合であったため情報が豊富であったことが幸いしました。

この度はほんとうに良い勉強になったなぁと思います。
適度に痛い思いをしたおかげでデータに対する思いを再度引き締められました。


勉強代は
修理キットが5000円弱。
パソコンの新調で15万円。
この一件で得た教訓プライスレス。



ちなみに、この不具合を発症するトリガが不良セクタの発生なので、
そろそろ発症し始める人も多いんじゃないでしょうか・・・・

これは「データが亡くなるとこんなに困るんだ。バックアップはしっかりとろうね」と言う
seagateからの少しキツメの教育なのかもしれません。


あなたのHDDは大丈夫ですか?
バックアップは今すぐ、そして確実に。
このエントリーをはてなブックマークに追加
LINEで送る

時限爆弾が・・・

HDDのクラッシュと思っていたのが実はHDDファームの不具合だと判明
よくよく見てみれば2008年頃に騒がれたニュースで、この記事自分も読んだことあるやん・・・

そのころは仕事が忙しく、『あーそんなことがあるんやぁ、大変だぁねぇ』位にしか認識がなく、
まさか自分が使っているHDDがそれだとは思っても見なかった。


ファームウェアの不具合としては不良セクタの発見とシャットダウンのタイミング次第でHDDの起動に失敗する様になるという物。

■seagate公式発表記事
http://seagate.custkb.com/seagate/crm/selfservice/search.jsp?DocId=207931&NewLang=ja


公式な見解はあってもデータの復旧の対応はしてもらえないようで、その手の復旧サイトに頼めばほぼ10万近くのお金が飛んでいく・・・

ぐぐーる先生によればRS232C経由でTTL通信すれば解除できるっぽいが、それには通信ケーブルの自作が必要で、しかも結構難しそう・・・

そこであるんじゃないかなぁと思いヤフオクを開けば、やっぱり売ってた。


というわけで100%復活はできないかもしれないけど、これでなんとか復帰してくれないかなぁ・・
やっぱり諦めきれない、あのデータ、このデータがあるんだよおおおおおおお
このエントリーをはてなブックマークに追加
LINEで送る

パソコン購入のその後

実は、当日にはできなかった。

原因は熱暴走とのことで、話をよくよく聞いてみればCPU、グラボ共にアウト。
今時のCPUは100%負荷かけ続けると標準ファンでは熱暴走するんかい・・

そんな訳で店員様と対策会議。
自作でやっていたらこれ、諦めて低負荷を維持する、運用での対策や定格以下にして発熱を抑える方向に持って行ったりするんだけど、そこはショップ組み立ての強み。
部品交換での対応をお願いできました。

アリガタヤ アリガタヤ。

方針としては、
・ケースの容量アップ
・グラボのグレードダウンと信頼性向上
・CPUクーラーの導入

だったのですが、出来上がったマシンを見て驚愕。
気がつけば自分で組んだ場合絶対にありえない構成に
・ファンが6つもついたクルクルパーなケース(しかも赤く光る!)
・CPUはファン数の増加を嫌って気がつけば水冷式
・グラボは贅沢の極みELSA様

なんだこの廃人仕様は・・・
スペックこそ最上位ではないものの、その扱いは最早ハイエンドと言わざるをえない。
それでもベンチマークかけると”余裕のある状態”とは言えないというのだから恐ろしい・・


なんていうか、昔から自分の作っていた自作品の殆どは熱に対してあまりにも脆弱だった気がする。
それが原因で不安定な仕上がりのPCが多かったんじゃないかと今頃になって思う・・

それとも最近のPCの発熱量が異常なのか、
それともSLIという構成そのものが悪なのかもしれない・・・
このエントリーをはてなブックマークに追加
LINEで送る

規模感

今日はHDDが壊れた関連で大須へ行ってきた。
HDDのみ買っては見たものの長らく使っていなかったDVDドライブまで壊れており
これはまぁ買い換えろということかなと思った

そこでBTOを狙いあちこち回ってみるのだが、とんとみないうちに価格帯は大きく変わっていた。

まず驚いたのがメモリの安さ、2ギガで二千円て・・・
1テラのハードディスクが5千円で、
ミドルクラスのグラボが1万ちょいちょいと、もうわけわからん状態


しかしながら、目的のBTOパソコンはちょうどほしいスペックと価格のものがなく、彷徨うハメに。

その原因はBTOではSLIなんぞという基地外構成は当然のごとく無く、オーダーメイドになるため即納はできないという。そりゃそうだ。

自分で拡張する方法も考えていたのだが、保証を重視せよとの相方の厳命もあり、選択肢から外すと即納ができない状態・・・・・弱った。

そんな中TWOTOPさんは対応が違った「ちょっと相談してみます」とカウンターへ、それほど話す様子もなくOKとのこと。ありがたい!
ただし、構成の関係で半日時間がほしいとのこと。ダメなんて言うわけありませんがな。


しかし当初はセミオーダー品が、話していくうちに結局フルオーダー品となり、それでも工賃たったの一万で即納してくれるとか、本当にありがたい。

当初予定していたスペックから思えばワンランク上で予算も数千円程度足が出たが、店員さんが二人もついてくれたおかげでかなり信頼できる構成に。

ただでさえ即納のわがままを言った挙句、最後の最後に値段交渉までかける迷惑な客に、常時にこやかに対応してもらい、非常に満足良く買い物ができたと思う。


しかしながら、対応をしてくれたこの二人のバランスがなかなか良く、
一人は愛嬌のいい絶対価格を気にする安定性はギリギリでもオッケータイプ。
もうひとりは客の話をよく聞いてより良いものをおすすめする職人タイプのタッグだった。

前者の店員が後輩で、その後輩の少しおっちょこちょいなところを先輩がうまくカバーしていて非常にいいタッグだと思う。

あとは奥のほうで在庫整理をしていた怖者てのベテランの組み立て係がやってくれるとの事で、非常に安心出来る買い物だった。


昔はよくあった秋葉原の路地裏店舗の規模感がすごく良かった。
それぞれがそれぞれの技術を理解しあっていて、それを尊重している感じで
6人ほどの店舗なんだけども、調度良い規模感だなぁと思った
このエントリーをはてなブックマークに追加
LINEで送る

結果。

モデルインスタンシングを試した結果・・・ダメでした。

勢いよく実装して、さぁHLSLを実装という段階でようやく問題点に気がつき
結局実行することもありませんでした。

というか物理的に実装不可能な方法で実装しようとしていたので、
「あ・・」という絶句の後、実装を断念しました。



そして、今朝・・・・
HDDがお亡くなりになったぽい・・・・・ショック(つд ;`)


自分ルールであったはずの2年縛りを無視して
なぁなぁでその倍の期間利用したのだから、当然の報いか・・・
しかし、高校時代からのデータのほとんどが消えた計算になる訳で・・・

まぁ、死に方がクシャミじゃなくてROM死にっぽいので、
いつか業者に出すのもいいかもしれない。
このエントリーをはてなブックマークに追加
LINEで送る

別スレッドからフォームコントロールを呼ぶときの注意

label1.textに値を代入しようとしたら”CrossThreadMessagingException”なる例外がっ

たかだかラベルにテキスト送信するだけでなんで例外が出るのかと思いきや、
別スレッドからのフォームコントロールプロパティへのアクセスは.Net2.0からの仕様変更で
そうなったそうで。

よくよく使用箇所を見てみるとたしかにフォームオブジェクト外からのイベント呼び出しようで、別スレッドっぽい。

そこでぐぐーる大先生で検索してみると、スレッドセーフだとかコントロール スレッドだとか、
妙に小難しい単語が並んでいて、サンプル見てもデリゲートとか見慣れない方法が連なっていて、
初心者には厳しいんじゃないかと思う・・


んで、簡単な対処方法を以下にご紹介

this.Invoke( //このthisはform1なので、別オブジェクトからの場合は注意が必要
(MethodInvoker)delegate() {
label1.Text = "hoge";
}
);

これでかなり簡単に、かつソースの見た目もほぼそのままコーディング出来る。
これすらも面倒だと言う人は、例外そのものを発行しなくなるオプションがあるそうなので、
そっちを当たってみるといいかも。
このエントリーをはてなブックマークに追加
LINEで送る

この手があった

前回の続き。

どうにも2パスで書くのが納得行かなかったので、
なんとかいい方法はないかと頭をひねっていたのだが、
ふと同じモデルを大量に描画する場合の高速化手法で
モデルインスタンシングってのがあったのを思い出した。

たぶん、これなら2パスじゃなくても行けそう。
DRAWの発行は一回、描画も一回、メモリ転送は一モデル分+α程度なのでこっちのが速いんじゃないかと思いたい。

比較する余裕が無いので、2パスとどっちのが早いかは他の人に任せて、
メンテナンス性を優先して自分はこっちで実装する。
このエントリーをはてなブックマークに追加
LINEで送る

まだ遅い

texture2d.getdataを2重ループから放り出してもなお遅かった・・

「くそっ、どこかに答えがあるはずだ!」とグーグル先生に聞いてみると
自分のサイトがヒットしたりして少し凹んだ。


んでよく良く調べてみると、やはり矩形のサイズによっても取得速度に変化がある事が分かった。
そこで、現在テクスチャの縦幅を1パーツ32固定で作成していたのを可変として
取得処理の絶対的な負荷を下げてみるつもり。

また取得処理そのものが遅いので、現在2つのレンダリングターゲットに、
それぞれ、ポジション、ノーマルの描画をし、texture2d.getdataを二回発行しているのを
一つにまとめる方法を試してみたいともう。

ただ、これってMRTなら一度の描画で済むのを2パスで2回書くことになるので、
そのあたりのうまく高速化できるかどうかを見極めたいところ。


しかしながら、本当にGPUの処理結果をもう一度CPUで処理しようというのは、
どうしようもなく低速になってしまうんだなぁとつくづく思った。

そういう意味では、悪者はtexture2d.getdataではなくアーキテクチャなのだなぁと。

いやしかし、それはよくよく考えれば設計者の選択の結果であって、
本当に問題なのはそれを生かせぬ己か。
このエントリーをはてなブックマークに追加
LINEで送る

XNAでのGPGPU処理時の注意点

念願のGPGPUをどうにか完成させ、
「これでありあまっていたGPUパワーをフルに使えるぜ!」と喜んだのもつかの間、
ほとんどの処理をGPUに回してコーディングを行ったはずなのにCPUの負荷が下がらない
・・・はて?


当初、メモリへの型変換の処理が遅いのかと思って調べを進めていたが、どうも違う。
原因はたったひとつの関数で

RenderTarget2d.GetTexture().GetData()

こいつがとにかく遅い。
その遅さたるや、代車で借りた1リッターマーチが、東海北陸道の上り坂で、
アクセルべた踏みしても80km出なかった、あの衝撃に近いものがある。

これを呼び出す回数はとにかく抑える必要が有る。
2重ループの中に放り込む等というのは絶対にしてはならない。


これの対策法としては、処理の遅さがテクスチャサイズにほとんど比例しないので、
出来る限り一枚のレンダーターゲットに情報をまとめ、
GPUで行った処理結果の取得回数を減らす必要が有る。

当初は汎用的に作っていたが、
GPUで処理する際にはテクスチャと言う名のメモリを管理する為に
パラメータを与える必要がありそう・・
このエントリーをはてなブックマークに追加
LINEで送る

 | HOME | 

PAGE TOP ▲

Appendix

■春条

■春条

生息地は愛知
車と甘い物が好きな31歳
特技は無限昼寝

MONOからSharpDXを使う
変態的な手法で、
.NET Frameworkを使わずに
ゲーム作りやってます。

Search

Calender

« | 2011-03 | »
S M T W T F S
- - 1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31 - -

Twitter

Recent Entries

DTIブログポータルへ
このブログを通報
Report Abuse

利用規約