「 2015年01月 」一覧

VisualStudio 2012 のリモートデバッグ

今更ですが VisualStudio 2012 のリモートデバッグが思いの外、進化していたことがわかりました。
リモートの環境で、リモートデバッグのモニターを起動しておくのは従来から変わらないのですが、今までの VisualStudio 2010 まではリモートに手動なりスクリプトなりでビルドした実行体や必要なファイルをコピーしていました。これが 2012 からはリモートデバッグの設定でできるようになりました。

この機能を使うためには、プロジェクトの設定を変更する必要があります。 構成マネージャーを開き
配置」の項目にチェックを入れる必要があります。デフォルトではここにチェックが入っていません

その後、プロジェクトのプロパティで、デバッグを 「ローカル Windows デバッガー」 から 「リモート Windows デバッガー」 に変更します。これらの各項目についてですが、以下のようになります。

  • リモートコマンド: ターゲットでの実行体のフルパスを記述
  • 作業ディレクトリ: ターゲットで配置した実行体のフォルダパス
  • リモートサーバー名: ターゲットのIPアドレスを記述
  • 配置するディレクトリ: ターゲットに実行体を配置するフォルダパス。作業ディレクトリと同じもの設定が無難
  • 配置するファイル: 実行体以外で転送したいファイルを列挙

これらを設定してみた図が以下のようになります。
vs2012_remote_dbg_config

これでビルド&実行の際に、リモートに必要なファイルが転送されて、即デバッグ開始できるようになります。
今までの一手間がずいぶんと楽になりました。VisualC++のデバッグランタイムもまた配置できるようで、わざわざスタティックリンク版を用意しなくてもよさそうなのも便利です。

その他

配置におけるプロセスですが、どのポートで通信してるかなと思ったら、 devenv からターゲットの 4016 ポートに向かって通信していました。 FW で引っかかるようだったらこのあたりを除外設定するとうまくいくかもしれません。
手元の環境では Norton Internet Security が入っていますが、上記の設定だけでうまく動作し、 FW の例外設定などは不要でした。


MIPS Creator CI20 で OpenGL 使えるようになった

以前に試したときには OpenGL 2.1 がまともに使えなかったのですが、 2015/01/15 に公開されたベータバージョンのイメージからは使用可能になったようです。

以前のものは OpenGL 2.1 対応といいつつもなぜかそれ以降の拡張も使用可能であるとAPIの結果は返ってきたのですが、今回改めて確認してみると正しい範囲になったような感じです。

基本的には OpenGL 2.1 の必須+浮動小数テクスチャへの書き込みサポート&MSAAのレンダーターゲットを使用可能といった範囲になっているようです。以前使えるように見えたインスタンシングやジオメトリシェーダーが使えなくなってしまった点は残念な気がします。

イメージを適用する

基本的には配布サイト(http://www.elinux.org/CI20_Distros) から該当イメージをダウンロードし、SDカードに dd コマンドを使って書き込んで、 MIPS Creator CI20 に差し込んで eMMC の内容を更新という手順で OK です。
 ただなるべくなら eMMC を常用したくないので SDカードからの起動および通常使用としたいところです。そこで入手したイメージから起動SDを作る方法を示したいと思います。

起動SDを作るためには、以前の記事内容(MIPS Creator CI20 を SDカード起動にする)を参考にします。
この説明の課程で出てくる uImage をどのように作るかが今回は問題になりますが、 rootfs2015-01-15_16_49_47.tar の中に含まれている /boot/vmlinux.img をその uImage の代用とします。それ以外は同様で、以下のコマンドのようにしてSDカードを構成します。

# ./make-flash-card-ci20-sd.sh /dev/sdX vmlinux.img rootfs2015-01-15_16_49_47.tar

問題なければ、書き込んだSDカードで起動できると思います。 SDXC の 64GB のものを使用しましたが、速度は出ませんがうまく動いているようです。

コンパイラ

今回の 20150115 版のカーネルおよびイメージでうまく動くことが確認できたので、クロスコンパイラを作り直すことにしました。
MIPS Creator CI20 用の環境としてクロスコンパイラは整備されていないようだったので、 Ubuntu 用, MinGW 32bit/64bit 用として3種類のアーカイブを用意することにしました。
こちらのページで配布していますので、必要な方はこちらからどうぞ。


クロスコンパイラ (MIPSCreatorCI20 / Jetson TK1)

生成したクロスコンパイラのアーカイブを置いておきます。
不具合等があるかもしれませんので、使用する際には自己責任でお願いします。
シンボリックの解決の問題で、 tar アーカイブを展開する際にエラーメッセージが出るかもしれませんが、問題ないかと思っております。

Jetson TK1

Ubuntu 上のクロスコンパイラはメーカーが公式に用意してくれているため、生成していません。

MIPS Creator CI20

補足

これらのコンパイラは crosstool-py というツールを用いて、Ubuntu 上で作成しております。
また MinGW 版は Windows7 SP1 にて動作確認を行っております。


Jetson TK1 のSDカード起動について

maker faire tokyo 2014 にて購入した Jetson TK1 @NVIDIAケース付き での話になりますが、 SDカードからの起動において若干問題がありそうです。もしかしたら製品バージョン関係ないのかもしれませんが。

その問題とは、 SDXC のカードではうまく起動できない、という点です。たまーに起動成功したりもするようですが、条件を特定できませんでした。失敗の時にはコンソール画面で何らかのエラーコールスタックがつらつらと表示されていました。

SDXCカードのメーカーによるものかと2社ほど試してみましたがどちらもダメで、 SDHC のものなら大体のメーカーのものでもうまくいくような感じでした。試したものは 21.2 のバージョンの L4T です。もしかしたらそのうち U-BOOT なりカーネルなりのバージョンが更新されて、 SDXC を気にしなくても夜なる日が来るかもしれません。今のところは、 SDHC あたりのカードを想定しておくと余計なトラブルに巻き込まれなくて済むかなと思います。


DirectX9 on Windows 7 でメモリの消費調査

今回は DirectX 9.0 を用いた場合ではどんな感じになるのかを調べてみました。環境は Windows 7 (x64) です。また DirectX 9.0 と表記していますが、実際のところは DirectX 9.0 EX のことを指すものとします。

Windows XP までの頃は VRAM の仮想化というものがなく、デバイスロスト発生のためのケアが必要になっていました。その代わり VRAM にデータを送ってしまい、メインメモリは消費しないということができたように思います。(もしかするとできていなかったのかもしれませんが、今更検証価値も低そうなので手元でテストしていないです・・・。)
一方で Windows 7 になってVRAM仮想化が導入され、VRAMの空き容量など取得が難しくなってきました。 DirectX 9.0 は動くものの、その挙動は XP のころとはまた違ったものになっていると予想されます。それなのに検証をしていないままだったので、 VRAMの情報取得という武器ができた今、調べてみようと思ったわけです。

NVIDIA (Geforce9800) の場合

安定状態になってから頂点バッファ 32MB を D3DPOOL_DEFAULT にて作成しました.

状態 メモリ(MB) Dedicate(MB) 共有メモリ(MB)
定常状態 1054.6 47 13
VertexBuffer作成 1回目 1086.7 80 13
VertexBuffer作成 2回目 1119.3 112 13

どの場合においてもメインメモリ 32MB 程度消費し、Dedicate のメモリ 32MB ほど消費している結果となりました。

AMD (RADEON) の場合

状態 メモリ(MB) Dedicate(MB) 共有メモリ(MB)
定常状態 1028.9 45 22
VertexBuffer作成 1回目 1061.1 77 22
VertexBuffer作成 2回目 1093.8 109 22

こちらの場合においてもメインメモリ 32MB 程度消費し、Dedicate のメモリ 32MB ほど消費している結果となりました。

実験その2

描画フレームを回しながら、 100 フレームごとに頂点バッファを確保し描画するという定番のプログラムで実験してみました。
上記の消費メモリが永続的なものではなくテンポラリ扱いならば、相当の数のバッファが作れるはずです。

しかし予想外の結果になりました。

メインメモリの消費が、自分のプロセスに対して発生していました。どうやら D3DPOOL_DEFAULT では自プロセスのどこかにバックアップのバッファが存在するようです。

GTX 750Ti 2GB の状態で普通の 32bit アプリケーションで実行の場合には、x64環境といえども、 1プロセスで使えるサイズは 2GB まで。そのため VRAM 使用量が 1GB 程度のところで DirectX がバッファの作成に失敗しました、とエラーを出しました。このときのプロセスの状況を調べてみましたが、消費されている仮想アドレスが 2GB 近かったです。
 一方で、 32bit アプリで LAA オプションをつけて再実行してみると、今度は VRAM 使用量は 1.7GB 程度にまでなり、プロセスの仮想アドレス使用量は 4GB 近くにまでなっていました。

※ このプロセス内での状況を知るのに VMMap というツールは便利です。

まとめ

DirectX 9.0 の場合においては NVIDIA も AMD も同じような挙動となることを確認できました。またどちらの場合においても使用するリソース分、メインメモリも消費していることが確認できました。これはこれで挙動把握さえできてしまえば、扱いやすそうです。
ただ注意が必要であると感じたのが、自分のプロセスの仮想アドレス空間にバックアップ先を確保するため、メモリ不足よりも自身の仮想アドレス空間を枯渇させてしまうのが早そうに思います。 64bit 環境を必須とするなら 32bit アプリケーションの場合、 LAA 必須といってもいいレベルだと思いました。
 この場合、よいビデオボードを使っていて 「 4GB の VRAM 全部使いきる DirectX 9.0 アプリケーションを開発してやるぞ。 ただし 32bit アプリケーションだけどなっ」 という夢はかなわないことが判明しました。そんな人は少数派だとは思いますが・・・。


DirectX11の場合のシステムメモリとVRAM消費について

今までは OpenGL の場合を調査してきました。今回は DirectX11の場合を調べてみようと思います。ドライバが一緒ならきっと同じ傾向を示すんじゃないかなと予想して実験をスタートです。

実験

DirectX11のプログラムとして、100フレームごとに頂点バッファ 32MB を確保し、次フレーム以降はこのデータを使って描画するプログラムを作成しました。
各フレームでの各メモリの使用状況を取得して、グラフ化しました。

実験は以下の環境で行いました

  • GTX750Ti Windows 7 347.09
  • RADEON HD 5450 Windows 7
  • RADEON HD 5450 Windows 8

結果

それぞれの実験結果のグラフを以下に示します。

nvidia_memory_graph_dx11_win7

radeon_memoy_graph_dx11_win7

radeon_memoy_graph_dx11_win8

NVIDIA も AMD も同じような挙動を示す結果となりました。また VRAM が使用可能な状態であれば、追加のシステムメモリの消費もなく良好といえそうです。(とはいっても追加のメモリを要求されたのは NVIDIA OpenGL の場合のみでしたが)。さすが仕様が決まっている DirectX といえるかなと思います。
 ちなみに RADEON のほうのグラフ末尾がおかしなことになっていますが、このときアプリは相変わらずフリーズ状態になってしまいました。ですので、システムメモリを VRAM リソースとして使用始めたらやや注意が必要になっていきそうです。ビデオメモリ仮想化が入ったといわれる現時点においても、なるべく搭載量を超えないようにするのはマナーとしておいたほうがよさそうです。


OpenGLでOut of memory とメモリの関係 (AMD)

今まで NVIDIA のもので調べていたので今回は同じプログラムを AMD Radeon 5450 を使ってデータ取得してみました。

  • Windows 7 x64 (2GB)
  • AMD Radeon HD 5450 (1GB)
  • ドライバは Catalyst Omega 14.12

プログラムは OpenGL を用いて 32MB 単位で頂点バッファを 300 フレーム間隔で確保していくものです。作成後、 Out of memory のエラーが返ってきたら終了します。

実験結果

何度か動かしてみましたが、 GL_OUT_OF_MEMORY のエラーが取得できませんでした。あふれた状態になったと思われるときには、アプリケーションがフリーズ状態に陥りました。 SwapBuffers の実行内部で無限ループしているような気配でした。
 この状況になるまでのデータで、システムの使用メモリ、 VRAM の使用量、共有メモリの使用量をグラフ化してみたものが以下のようになります。 NVIDIA の場合とは傾向が違っていておもしろいです。

radeon_ogl_outofmemory_log
今回の場合は、 VRAM に配置できる場合にはそちらに配置して、システムのメモリは消費しないようにみえます。実際にこのタイミングではプライベートヒープが増えているような感じではありませんでした。 観測タイミング次第によっては glBufferData の中身のテンポラリの DMA 転送タイミングで作業バッファぽいものが見えたりしますが、数フレーム後解放されたりしました。 VRAM に配置できない状況になったときに、初めてシステムのメモリを消費しての共有メモリ使用増加が観測できました。おおよそ 1.6GB ほどの使用量になったときにアプリケーションがフリーズ状態に陥ったように見えます。この環境ではビデオアダプタのプロパティで確認できたのが「利用可能な全グラフィックスメモリ 1791MB」とあり、最大値であるこの値にまで到達したのかなと思っています。

感想

AMD のグラフィックスドライバは余計な(?)システムメモリを消費しなかったので、 OpenGL 実装でも無駄はないという点に関心しました。一方で、メモリあふれのエラーを検知できないのはマズイですね。無駄なメモリは確保しないから、溢れさせないよう気をつけてアプリケーションを実装しましょう、ということでしょうか。

おまけ

同じようなテストを Windows8 (64bit) に切り替えて行ってみました。おおよそ同じ傾向になりました。ただシステムメモリの細かな変動が観測され、作業メモリとして使用している部分がみえたのかなと思っています。(これは以前に glBufferData 直後での内部動作でそのような動きを見せたためです。)
ドライバが標準的に導入されたものを使用し、 Catalyst Omega ではない点ももしかすると影響しているかもしれません。
radeon_ogl_outofmemory_log_win8


OpenGL @NVIDIAでのメモリ調査

NVIDIA Geforce で OpenGL を使った場合のシステムメモリの消費について調べてみましたが、サイズ可変でどのくらい消費量が変わるのか、というものでした。また API 実行の各タイミングで計測したのみで、時間経過を考慮していませんでした。

今回はサイズは固定し、 100 フレームに 1 回頂点バッファを確保して描画するという方法を試してみました。また描画に使用されない場合は処理をされないという可能性を除外するため、次フレーム以降は確保したバッファを用いての描画を行うようにしています。

確保のタイミングで、以前の確保時のデータとどのくらいメモリ使用量が変動するかをグラフ化したものが以下となります。
nvidia_opengl_temporary

結果

NVIDIA の場合、 OpenGL の作業用のメモリとして多めのメモリを使用する傾向にあるようです。しかしフレームの経過とともにその作業メモリを解放も行っているようです(そうでないと差分デルタが減った説明ができない)
多くの場合は、 VRAM 側に確保したメモリサイズと同じ程度のメモリを消費すると考えて良さそうです。


VRAM使用量を取得するアプリ&ライブラリ更新

VRAMの使用量をグラフ表示するアプリである ViewVRAM を更新しました。また内部で使われているライブラリも更新しました。
今回の目玉は 64bit 環境に正式に対応したことです。

また複数のデバイスが搭載されている場合において、見づらくなってしまっていた点を対処しています。

ViewVRAM の情報はこちらをご覧ください。
ViewVRAM のライブラリ部分である vramspacelib についてはこちらをご覧ください。

その他

C# でもっと見栄えのする簡単なグラフ描画コンポーネントってないもんですかねぇ・・・。


OpenGLでOut of memory とメモリの関係

細かな単位で OpenGL の頂点バッファをたくさん確保していたらこんなエラーに出会いました。ちなみにプログラムの実行タイミング次第では OpenGL で OUT_OF_MEMORY のエラー状態がちゃんと返りました。エラー返す前に異常系に落ちたという感じでしょうか。
nvidia_driver_oom

この症状が出るまでの様子を、使用システムメモリ、使用VRAM量、使用中の共有ビデオメモリ量、との値をグラフにしてみたものが以下となります。

nvidia_ogl_outofmemory_log

実験プログラムについて

Windows 7 x64 (16GB) の環境で、 Geforce GTX750 Ti (2GB) を装着しています。
300 描画フレーム間隔で、 128MB の単位で頂点バッファを確保するプログラムを動作させています。また、確保後は次のフレーム以降、バッファ先頭だけ使ってではありますが描画処理も行っています。

このようにしている背景としては、描画されないデータは処理されないのでは?という点と SwapBuffers が呼ばれない場合、作業メモリが解放されないのではという疑惑があるためです。そのために、描画ループを回しつつ、定期間隔で確保実験するに至りました。

この結果について

実際の搭載 VRAM 量までは順調に VRAM 側にリソースが確保されるようです。それがいっぱいになると共有メモリを使うようになっていくのが見えます。このとき、ドライバのなかでデータの整理が行われるのか、一時的に逆転送など行い共有メモリ量が増加&VRAM側をパージしている様子がうかがえました。
また VRAM に確保されようが、システム全体の使用メモリは増加していくのがわかります(黒線のグラフ)。使用した VRAM リソースの合計は約3GBでした。

実験その後

VRAM の断片化とかあるかなと考えて、バッファのサイズを 32MB に減らして再実験しました。このときアプリケーションもまた 32bit ですが、 LargeAddressAware をオンにして 4GB までのアドレス空間使えるようにしてみました。
 しかしながら、4GB まで使えるようになったというような結果を予想していましたが、3GB付近でエラーとなってしまいました。アプリケーションのアドレス空間の問題ではないようです。エラーが出た際のプロセスの状況を探ってみると、 1.3GB 程度のメモリ使用量となっており、このときプライベートヒープで割としめられていました。そのブロック単位も 32MB ほどなっており、どうやら VRAM リソースとして確保した何かのコピー(もしくは実体の待避?)かと思われます。これらの情報は VMMap を見れば詳細にわかります。

このような状況になってもちゃんと動き続ける今の Windows や NVIDIA のドライバはすごいなぁと関心もした次第です。