Quantcast
Channel: shobomalog
Viewing all 40 articles
Browse latest View live

Direct3DとDirect2D/DirectWriteの連携

$
0
0

Direct3D 11.0とDirect2D/DirectWriteの連携を試してみました。

1. Direct3DとDirect2Dにまつわる面倒な話

Direct3Dは3DCGを高速に描画します。Direct3Dには2D専用の機能がなく、文字列表示もありません。Direct3D 9にはDirect3D Extensionとして文字列を描画するID3DXFontインターフェイスが用意されましたが、Direct3D 10で廃止となりました。

Direct3D 10からはDirect3Dの構造が大幅に変更されました。3D処理に直接関係のない各種バッファやディスプレイ・GPUの管理などをDXGIが管理することになりました。GDIやDirect3Dなどの描画コマンドは、全てDXGIを経由し、カーネルモードグラフィックスドライバに伝えられます。

Direct3D 10.1と同時にDirect2DDirectWriteが登場しました。Direct2DはGDI+などを置き換えるもので、GPUを使った高速なレンダリングに対応しています。DirectWriteはDirect2Dの一機能で、GPUを使って高速かつ高品質に文字列をレンダリングします。

Direct2Dは内部的にはDirect3D 10.1を使っています。よって、Direct3D 10.1とDirect2D/DirectWriteの相互運用は簡単です。しかし、Direct3D 11.0と連携させようとすると、DXGIを何度も経由しなければなりません。つまり、Direct3D 10.1リソース→DXGIリソース→Direct3D 11.0サーフェイスという面倒な変換を噛まさなければなりません。しかもDirect3D 10.1とDirect3D 11.0は完全に独立して動くため、DXGIの同期機構を使って同期を取らなければなりません

WPF + Direct2D のサンプル(サーフェイスの共有)に書いてあるように、Direct2DとDirect3D 10.1あるいはGDIとの相互運用パスは用意されていますが、Direct3D 11ではDXGIを経由しなければなりません。

めまいのする話はまだ続きます。DXGIを経由したリソースのやり取りでは、同期機構を使うことを知らせるフラグ(D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX)を立てる必要があります。しかし、スワップチェイン生成時にこのフラグを立てることができないため、レンダーターゲットをDirect3D 11.0とDirect3D 10.1(Direct2D)の間で受け渡しすることができません。つまり、Direct2Dの描画先となるテクスチャをDirect3Dで別に用意し、最終的なレンダリングを行う前にDirect3DとDirect2Dのレンダリング結果を自分でブレンドさせなければなりません。

Microsoftが提供するDirect2D/DirectWriteを使うソフト(Internet Explorer 9など)もDirect3D 10.1を使っているようで、Direct3D 11は蚊帳の外でした。

2. DXGI 1.2の登場と相互運用性の改善

この残念すぎる仕様は、Windows 8の登場とともに大きく改善されました。Windows 8ではDirect3D 11.1、DXGI 1.2、Direct2D 1.1とDirectWrite 1.1(新API名を参考に筆者独自の命名でありMicrosoft公式の記述ではありません)が新たに提供されましたが、Direct2DとDirect3D 10.1以外のDirect3Dともう少し簡単に連携できるようになりました。Windows Store Appを意識した新設計のため(特にDXGI 1.2の)APIが少し複雑になり、絶対的なソースコードの行数が大幅に減るわけではありませんが、同期機構が不要になるなど、使い勝手が良くなりました。

が、Direct3D 11.1など(厳密に言えばWDDM 1.2)はWindows 7に提供されないという噂が流れました。ところが先日、Microsoft公式ブログのDirectX 11.1 and Windows 7という記事で、WDDM 1.2に依存するAPIの提供が公言されました(WDDM 1.2自体には今の所対応しません)。Internet Explorer 10などがWDDM 1.2のAPIに依存しているため、フレームワークだけでも提供しないとIE10がWindows 7で動かないという問題が背景にあるようです。Windows 7でDirect3D 11.1の全ての新機能が使えるわけではありませんが、DXGIはWDDMの下位互換性があるため、WDDM 1.1までの範囲内である「制限されたモード」の下でWindows 8と同じAPIを使うことができます。

3. Windows 7で新APIに対応するための手順

Platform Update(KB 2670838)を当てることで各種コンポーネントがアップデートされます。しかし、現在はβ版のようです。筆者環境では正常に動作しました(Intel G45、GeForce 9800GTX+、GeForce 560Ti、AMD Switchable Graphics)。コントロールパネルからのアンインストールも可能です。

4. 副作用

DXGI 1.2になることで、いままでDirectX SDKに付属していたPIX(Direct3Dのためのデバッグツール)は使えなくなります。代わりに、VisualStudio 2012に付属するグラフィックスデバッグを使います。

しかし、グラフィックスデバッグはExpress版にはありません。前例から考えて、Platrform UpdateはIE10の自動配布と同時に行われると思われるので、アップデートせずPIXを使い続けるのは無理でしょう。実質有料化です。失望しました。Professional版は約6万円です(アカデミック版もなし。学生はDreamSparkがおすすめです)。

なお、Express版でもビルド・実行はできます。また、Direct3D 9のデバッグはVisualStudioでは提供されておらず、PIXが引き続き利用できます。

5. サンプルプログラム

長いのでpastebinに貼りました。一部力尽きているのはご愛嬌。

なお、DXGI 1.1で同期を使う方法は、Direct3Dのレンダリング結果と合成するにはシェーダを使わなければなりませんが、面倒だったのでDirect2Dのレンダリング結果をコピーして誤魔化しています。

DXGI 1.1で同期を使う方法(D3DD2DInteropMutex)

必要最小限の手順をざっと書くと次のような感じです。

  1. HWNDを指定してDirect3D 11デバイスとスワップチェインの作成
  2. DXGIアダプタの取得
  3. Direct3D 10.1デバイスの作成
  4. 共有用のDirect3D 11 2Dテクスチャの作成
  5. そのテクスチャからIDXGIKeyedMutexIDXGIResourceの取得
  6. IDXGIResourceから共有ハンドルのオープン
  7. 共有ハンドルからDirect3D 10.1デバイスに紐づけられたDXGIサーフェイスの作成
  8. DXGIサーフェイスからIDXGIKeyedMutexの取得
  9. Direct2DのレンダーターゲットにそのDXGIサーフェイスを指定
  10. IDXGIKeyedMutex->AquireSync()とReleaseSync()を使って同期を取りながら描画
  11. Direct2Dのレンダリング結果とDirect3Dのレンダリング結果を合成(サンプルではケチりました)

DXGI 1.2で同期を使わない方法(D3DD2DInterop)

こちらの手順も書いておきます

  1. Direct3D 11デバイスの作成
  2. DXGIデバイスの取得
  3. そのDXGIデバイスを指定してDirect2DデバイスDirect2Dデバイスコンテクストの作成
  4. DXGIアダプタの取得
  5. HWNDを指定してスワップチェインの作成
  6. そのスワップチェインからDXGIサーフェイスの作成
  7. そのDXGIサーフェイスからDirect2Dビットマップを作成
  8. Direct2Dデバイスコンテクストのレンダリング先にそのDirect2Dビットマップを指定
  9. 普通に描画

後者の方法では、前者の方法より取得すべきもの(IDXGIKeyedMutexとか)が大きく減っており、面倒くさい感じが幾分か抑えられていると思います。

なお、デバイスロストは考慮していません(忘れていました(:P)。

6. 既知の問題

同期を使う方法(面倒くさい方法)では、グラフィックスデバッグもPIXもバグってしまうようです。共有サーフェイス周辺でコケますが、原因は分かりません。Microsoft公式の共有サーフェイスのサンプルでもデバッグできなかったので、仕様なのかもしれません。

同期を使わない方法(あまり面倒くさくない方法)も、Windows7上でのグラフィックスデバッグではコケます。原因不明です。当たり前ですがPIXはDXGI 1.2に非対応なのでダメです。しかし、WDDM 1.2ドライバがインストールされたWindows 8(GeForce 9800GTX+)ではデバッグできました。

まとめると、Direct3DとDirect2D/DirectWriteとの連携を使うグラフィックスデバッグでは、同期を使わない方法で、Windows 8とVisualStudio 2012 Professinal以上とWDDM 1.2ドライバが必須という状況です。通常の実行はいずれも問題ありません。

対処方法をご存じの方は、コメントを入れてもらえると助かります。

そういえば、NVIDIA Parallel Nsightのグラフィックスデバッガだとどうなるんでしょうね。気が向いたら試します。

7. 余談

もう文字列のテクスチャ貼り付けでいいような気がしてきた

■参考文献

  1. Surface Sharing Between Windows Graphics APIs (Windows)
  2. Devices and device contexts (Windows)
  3. Direct2D と Direct3D 11 の共有方法

おしり



各種並列処理ライブラリの実験

$
0
0

OpenMP、並列パターンライブラリ(PPL: Microsoft Parallel Patterns Library)、C++AMP(C++ Accelerated Massive Parallelism)をちょびっと試しました。

Microsoft Visual C++シリーズでの開発を前提とします。

0. その前に

C++11のラムダ式の知識が必須(このへんとかを参照)

1. 動作条件

OpenMP : Visual Studio 2005以降(Express版ではWindows SDKが要るかもしれない)

PPL : Visual Studio 2010以降

C++ AMP : Visual Studio 2012

2. 各ライブラリの違い

OpenMP : クロスプラットフォームで対応するコンパイラが多い。pragmaディレクティブで簡単に並列化。

PPL : Microsoft独自。「同時実行ランタイム」の中で提供。ラムダ式と相性が良い。結構多機能。

C++ AMP : Microsoftと(たぶん)AMDが開発、規格はオープン。GPGPU(Direct3D 11のCompute Shaderに変換される)。PPLと統合したっぽい。

3. サンプル

奇偶転置ソートを試しました。符号付き32bit整数を昇順に並べ替えます。ソートのアルゴリズムとしては悪い(最悪計算量がO(N^2))ですが、アルゴリズムがシンプルなので使いました。本気で並列処理でソートするならばbitonic sortやradix sortが良いでしょう。

長いのでソースコードはpasetbinに置いておきます

oddEvenSort()が基本形です。oddEvenSort2()はループ変数が0から順になるように変形しています。

oddEvenSortOpenMP()がOpeMP版です。for文に#pragma omp parallel forをつけるだけです。コンパイラの設定でOpenMPを有効にしないと、無視されてシングルスレッドになるので注意してください。

oddEvenSortAmp()がC++ AMP版です。GPUのスレッドは0番から順にIDが振られるので、oddEvenSort2()がベースです。concurrency名前空間のarray_viewクラスが、CPUとGPUのメモリ空間の接続する窓の役割をします(Direct3D 11のUnordered Access Viewに相当)。extentがスレッド数です(OpenCLのget_global_id()に相当)。parallel_for_each()で処理を開始します。restrict( amp )をつけると、そのコードがGPU上で動作させることを知らせます。

oddEvenSortPPL()がPPL版です。.NET Framework 4.0のParallel Extensionsにソックリです。

4. 実行時間

N = 50000のときの時間を計測しました。単位は秒(小さいほど良い)。Visual Studio 2012 Professional。

Celeron(Penryn-L, 2core) + GMA4500MHD

Sort1 6.396
Sort2 6.302
OpenMP 4.649
PPL 39.811
Amp (ソフトウェアエミュレーション)10分以上

i7(SandyBridge, 2core/4thread) + Radeon HD 6630M

Sort1 2.106
Sort2 1.965
OpenMP 2.200
PPL 14.274
Amp 15.600

5. 適当に考察と補足

奇偶転置ソートでは処理が単純すぎて、並列化のコストの方が大きくなっているようです。

C++ AMPの実行時、GPU負荷は約60%でした。CPUの呼び出しコストの方がボトルネックになっていると思います。

6. 他の並列ライブラリ

Visual Studio単体でできる並列処理ライブラリ以外にも、次のようなものがあります。

Intel TBB(Threading Building Blocks) : Intel製のオープンソース。AMD x86プロセッサでも動く。

Apple GCD(Grand Central Dispatch) : Apple製。OS X Snow Leopardの目玉機能の一つ。

C=(CSTRIPES) : よくわからん。気付いたらOpenCVが対応していた。Windows/Linuxのx86/x64向け。

NVIDIA CUDA : NVIDIA製。GPGPU。Tesla/Quadro/GeForce専用。

Khronos OpenCL : Apple提唱、クロスプラットフォーム。GPGPUも可能。

OpenACC : たぶんNVIDIA提唱。OpenMPのGPU版。


バイトニックソートの並列処理

$
0
0

前回、並列処理の実験として奇偶転置ソートを実装しました。今回は、平均アルゴリズム計算量がO(N・log^2(N))で高速なバイトニックソート(Bitonic sort)を実装しました。

前回の続きの記事なので、重複する解説は省きます。

1. アルゴリズム

実はよくわかっていません(:P

バイトニックソートのベースは(たぶん)マージソートで、分割と統治の繰り返しを行っています。


// 基本的なバイトニックソート
void bitonicSort( int num, int *ary1 )
{
  // 2の冪乗でなければ計算しない(5)
  if( ( ( num - 1 ) & num ) != 0 )
     return;

  for( int block = 2; block <= num; block *= 2 ) {
    for( int step = block / 2; step >= 1; step /= 2 ) {
      for( int idx = 0; idx < num; idx++ ) {
        int e = idx ^ step; // (1)
        if( e > idx ) { // (2)
          int v1 = ary1[ idx ];
          int v2 = ary1[ e ];
          if( ( idx & block ) != 0 ) { // (3)
            if( v1 < v2 ) { // (4)
              ary1[ e ] = v1;
              ary1[ idx ] = v2;
            }
          } else {
            if( v1 > v2 ) {
              ary1[ e ] = v1;
              ary1[ idx ] = v2;
            }
          }
        }
      }
    }
  }
}

具体的なアルゴリズムはググってください。

一部解説を入れておきます。(1)で、比較する要素を求めています(なぜかxorすると比較する要素番号と一致します)。(2)で、不要な比較を飛ばしています。実際の比較はnum(全要素数)の半分で(なぜ半分なのかは英語版wikipediaの図を見ればわかります)、3重目のfor文で飛ばしきれない分を飛ばしています。詳しくは後で説明します。(3)は、昇順か降順かを決めています。マージソートでは順序がどちらか一方向ですが、バイトニックソートは昇順と降順が定期的に入れ替わります。(4)は、交換するか否かの比較です。

先頭にある(5)は、2の冪乗か否かを調べています。マージソート系は、(工夫しなければ)2の冪乗でないとソートできません。2の冪乗はbitが1個しか立たず、1を引くとそのbit以下の全bitが立つ性質があるので、それを利用しています。まじめにfor文を回して2、4、8、16…と調べていくよりはるかに高速です。

2のべき乗でないソートはこちらを参考にしてください。ただ、並列処理はかなり難しそうなので、ここでは使っていません。代わりに、ソートする前に余分な要素すべてにINT_MAXを入れておくことで、2のべき乗でないソートができます。

2. GPGPU最適化

バイトニックソートはそのままGPUに移植できます。しかし、そのまま移植すると効率が悪すぎるので、GPUに適した形に変形します。

ここでは、分岐の除去を行いました。GPUは分岐に弱いことで有名ですが、これは複数のスレッドに対して同時に1命令しか実行できないことが原因です。分岐があると、真になるパスと偽になるパスの両方を実行することになり、結果として実行効率が落ちます(CUDAではWarp divergenceといって、避けろ避けろとうるさく言われます)。元のバイトニックソートはif文が4つもありますが、頑張って1つだけにしました。

// 条件分岐をできるだけ排したバイトニックソート
void bitonicSort2( int num, int *ary1 )
{
  // 2の冪乗でなければ計算しない
  if( ( ( num - 1 ) & num ) != 0 )
    return;

  for( int block = 2; block <= num; block *= 2 ) {
    for( int step = block / 2; step >= 1; step /= 2 ) {
      unsigned int maskLow = (unsigned int)step - 1;
      unsigned int maskHigh = 0xFFFFFFFF ^ maskLow;
      for( int i = 0; i < num / 2; i++ ) { // (A)
        int idx = ( ( i & maskHigh ) << 1 ) | ( i & maskLow );
        int v1 = ary1[ idx ];
        int v2 = ary1[ idx + step ];
        int isAsc = ( ( idx & block ) != 0 ) ? 1 : 0; // (B)
        int isBigger = ( v1 > v2 ) ? 1 : 0; // (C)
        bool needSwap = ( ( isAsc + isBigger ) == 1 ) ? true : false; // (D)
        if( needSwap ) {
          ary1[ idx ] = v2;
          ary1[ idx + step ] = v1;
        }
      }
    }
  }
}

(2)の部分に大きく手を加えました。改良前では、block==2、step==1のとき、(idx, e)はfor文によって(0, 1)、(1, 0)、(2, 3)、(3, 2)、(4, 5)、(5, 4)…となります。このとき、(1, 0)、(3, 2)、(5, 4)など、idxよりeが小さい場合、for文によってスキップされます(もう比較&並び替えは済んでいますから)。これはもったいないので、初めからidx = 0, 2, 4…となるよう工夫します。

step=1のときは1つ置きで飛ばされますが、step==2の場合、idx = 0, 1, 4, 5, 8, 9…というように、2回処理して2回飛ばすの繰り返しになります。このidxの値を条件分岐なして作り出すため、マスクビットとシフトを組み合わせています。要するに、step==2なら2bit目を常に0にし、本来2bit目以降にくる数字を3bit目以降にずらします。step==3なら3bit目以降をずらします。これでidxが作り出せます。その結果不要なループが減るので、(A)のループが半分で済みます。

(B)(C)(D)に3項演算子が出てきます。これも比較といえば比較なのですが、実は条件付き選択(移動)命令をに置き換えることで、条件分岐が発生しないようにすることができます。GeForce GPUのPTXならsetp.cc.s32命令、HLSLならmovc命令、x86 CPUならCMOV命令とかSETcc命令とかANDNPD命令とかに相当します(ちなみに今回のコードをVisualStdio 2012でコンパイルすると、x86ではテーブル参照(たぶん)とかSBB命令とかを使ったややこしいコードに、x64ではSETne命令やSETg命令を使ったコードになりました。CMOV/SETcc/ANDNPDは対応CPUが限られているので、代替命令になるのはしょうがないですね)。もちろん、3項演算子の2項目と3項目で何らかの計算を行っていると、そのパスを実行しなければならないので効率が低下しますが、今回は定数なので問題ありません。

ほかにも共有メモリを使えだとかコアレスアクセスにしろだとか色々ありますが(特にBitonic sortはNVIDIAのReductionサンプルと同じアイデアである程度コアレスアクセス化とカーネル関数呼び出しの削減できるはずです)、面倒なのでやりません。CUDA使いなら、GPU Computing SDKにBitonic sortのサンプルがあるので(Sorting Network)参考にしてください。ちなみに奇偶マージソートや奇数ソート版もあります。DirectXのサンプルにもBitonic sortのサンプル(ComputingShaderSort11)があります。参考までに、OpenCL版もAMDのサイトにあります。

3. ソースコード

長いのでpastebinに貼っておきます。(Githubにも用意する予定)

OpenMPはVisualStudio 2005、PPLはVisualStudio 2010、C++ AMPはVisualStudio 2012が必要です。OpenMPの使用にはコンパイラオプションの変更が必要です。

4. 実行時間

Sortが基本バイトニックソート、Sort2が無駄なループを削減したソート、AmpがSortのGPU移植、Amp2がSort2のGPU移植です。GPUは転送コストを含みます(PCI Express Gen2 x16)。

N=2097152

Core i7 2640M(SandyBridge, 2core/4thread) + Radeon HD 6630M

bench x86 x64
Sort 0.986 0.898
Sort2 1.267 0.836
OpenMP 0.865 0.899
PPL 1.843 1.064
Amp 0.283(FAILED) 0.375(FAILED)
Amp2 0.162 0.195

FAILED : 計算は完了したが結果が不正

Core i7 2600(SandyBridge, 2core/4thread) + GeForce GTX560Ti

bench x86 x64
Sort 0.823 0.868
Sort2 1.099 0.776
OpenMP 0.970 0.799
PPL 0.863 0.517
Amp 0.079 0.098
Amp2 0.047 0.036

.

5. だらだら考察

GPUはほんとに速い。基本バイトニックソートの6倍速いです。なぜかRadeonでのAmpは計算に失敗してしまいましたが、エミュレーション実行(後述)やGeForceでは問題なかったので、GPUかドライバの問題だと思います。

(表にはありませんが)Radeonについては実は速いのはNが十分大きいときだけで、N=65536だとAmp2が約7倍Sortより遅いです。N=131072と262144の境目くらいでCPUとGPUの速度が入れ替わります。これはおそらく関数の呼び出しコストでしょう。関数呼び出しを減らす、Nが小さいときはCPUで処理するなどの工夫が必要です。

なお、GeForceでは小さい数でもCPUより遅くなることはありませんでした(clock()関数での計測なので、マイクロ秒単位で測ったら差が出る可能性はありますが)。GeForceよりRadeonの方が関数呼び出しが遅いと聞いていましたが、嘘ではなさそうです。

前の記事の奇偶転置ソートもそうでしたが、OpenMPの効果が薄く、PPLはx86だけ大幅に遅くなってしまいます。使い方が間違っているような気がしますが、よくわかっていません。

なお、配列の並べ替えではなく、構造体配列の並べ替えをしたいこともあると思いますが、2.のCUDAのソースなどを参考にしてください(作るの面倒…)。

6. C++ AMPのデバッグと、コンパイルされたHLSLコードを見る方法

C++AMPはDirectComputeのラッパーで、DirectComputeはHLSLを使うことを前の記事で説明しました。HLSLコードはGPU上で走るので、普通の方法ではデバッグできません。

VisualStudio 2012でC++AMPコードをデバッグするには、プロジェクトのプロパティを次のように変更します。

構成プロパティ->デバッグ->「デバッガーの種類」を「GPU のみ」に変更

こうするとC++ AMPコードがCPU用にコンパイルされ、エミュレーション実行でデバッグすることができます。ただし、残念ながらCPUコードのデバッグと同時にはできません。

コンパイル後のHLSLコードを確認するには、次のように変更します。

1. 「構成」を「Release」に変更

2. 構成-> C/C++ ->コード生成->「ランタイム ライブラリ」を「マルチスレッド DLL デバッグ(/MDd)」に変更

3. C++AMPコードの先頭にブレークポイントを置いてReleaseモードで実行

4. メニューバーのデバッグ->ウィンドウ->逆アセンブル

このように表示されます

ただし、ReleaseビルドなのにDebugランタイムを使う状態なので、配布用にビルドするときは設定を戻してください(Debugランタイムは配布不可)。

情報元 : C++ AMP Disassembly?

7. PPLで高速ソート

実はMicrosoft公式のPPLのサンプルにBitonic sortがあります。こちらはparallel_for_eachではなくparallel_invokeを使った再帰のコードになっています。実行速度は、N=2097152のとき、i7 2640Mのシングルスレッドで1.052[秒]、マルチスレッドで0.512[秒]、i7 2600のシングルで0.624[秒]、マルチで0.187[秒]でした。…あれ?すごく速い…

…よくわかりませんが私のコードよりこっちを使えばいいんじゃないでしょうか(逃)


Wii Uスペック(随時更新)

$
0
0

WiiUのスペック(特にCPUとGPU)を調べて分かったことをメモしました。

【重要】情報の信頼性は保証しません

■CPU

IBM Power Codename Espresso
IBM 45nm SOI process
32.76 mm2
3core 1.24 GHz

ソース:任天堂公式、英語版Wikiepdia

■GPU

AMD Radeon HD(RV7x0 based)
TSMC 40nm process?
156.21 mm2
Direct3D 10.1(Shader Model 4.1)/OpenGL 3.2世代
320 or 400 core (Radeon HD 4650/4670相当?)
550MHz
GPGPU Ready
eDRAM 32MB

ソース:任天堂公式、西川善司の3DゲームファンのためのE3最新ハードウェア講座Eurogamer

■メモリ

2GB(アプリケーション1GB+システム1GB)
Hynix DDR3-1600 4Gbit
16bit x4 channel(12.8GB/s)
CPU / GPU共用

ソース:任天堂公式、AnandTech

以下、考察です。独自研究なので、間違っていても許してください

■Power7アーキテクチャの概要を確認

まず、CPUについて。Power7アーキテクチャベースというのは前から噂されていたので、間違いではないと思います(2013/2/23追記:PowerPC A2説が出てきたので、この主張は取り下げます)。元のPower7の仕様を書き出してみます。

64bit Power ISA v2.06
8core 567nm2 45nm SOI
3.0 – 4.14 GHz
Out-of-Order
SMT-4 (total 32thread)
L1 cache Inst 32kB(4-way) + Data 32kB(8-way) per core (latency : 2cycle, Write Through)
L2 cache 256kB(8-way) per core (latency : 8cycle, Write Back)
L3 cache 32MB eDRAM shared
TLB 512 entry
12 Execution Unit : 2x Fixed Point + 2x Load Store(+ simple Fixed Point ops) + 4x FPU(VSX) + 1 Branch + 1 Condition Register + 1 Vector(2x VMX ?) + 1 Decimal Float
Load 16Byte x2 / Store 16Byte bandwidth
6-way dispatch / 8-way issue
Memory Controller : DDR3-1600 8ch

ソース:POWER7 Technology & Features(PDF注意)、Hot Chips 21 – 3次キャッシュを内蔵したIBMの8コアプロセサ「POWER7」

PS3やXBOX360で使われているPOWER6に比べると、なんともリッチな仕様です。全体的にIntelの初代Core i(corename Nehalem)に似ています(そういう意味では、POWER6は3GHz以上で回るIntel Atomみたいなものかもしれません)。POWER6に比べて一番進化したのは、(1)Out-Of-Order、(2)SMT-4、(3)Execution Unitでしょう。もう少し詳しく見てみます。

Out-of-Order(アウトオブオーダ)は、命令実行順を並べ替えて効率よくExecution Unit(実際に計算をする回路)を回すテクニックのことです。POWER6は並べ替えできないIn-Order(インオーダ)でした。シングルスレッド性能の向上が期待できます。ブロック図によると、Execution Unitで共有してUnified Issue Queueを持っていて、これはInte Core iと同じです(AMDはUnifiedではない)。Reservation StattionやRe-order Bufferの数は不明です。

SMT-4は、サイマルテニアスマルチスレッディングのことです。Intelでいえば、ハイパースレッディング(以下HT)です。POWER6は1コアで2スレッド実行できました(HTと同じ)。Power7は1コアで4スレッド実行できます。ちょっとやり過ぎな気がしますが、マルチスレッド性能の向上が期待できます。先のソースでは、2スレッド実行で約1.5倍、4スレッド実行で約2.3倍の処理速度向上と書いてあります。SMT-4で4スレッド並列実行するために、命令のdispatch(割り当て)が1クロックで6命令もできるようになっています(IPC=6)。Core iの4命令(IPC=4、厳密にはIPC=5)、AtomやPOWER6やCortex-A8/A9の2命令(IPC=2)に比べても多いです。

Execution Unitは12個もあります。Core iが6個、次世代Core i(Haswell)が8個と比べても多すぎます。特徴的なのは、FPU(浮動小数点数ユニット)が4つもあることです。POWER6の浮動小数はPentium4の1/4くらいしか性能がなかったので、間違いなく大幅に高速化されるでしょう。一方、整数(Fixed Point、厳密には固定小数点数)は2つ、Load Storeと統合されたシンプル整数が2つの合計4個で、これは少なくはないです。ただ、disptchが6命令なのに整数が4つというのは、x86比ではちょっと少ない気がします。それでもPOWER6は(たしか)1つか2つしかなかったので、間違いなく性能は上がるでしょう(というかPOWER6が少なすぎ)。

キャッシュは3段構成ですが、これもL3が巨大eDRAMであることを除けば、構成がCore iに似ています。POWER6はL2キャッシュが巨大でしたが、Power7では小さくなりました。L3キャッシュで稼ぐ方向のようです。その代りレイテンシは小さくなったはずです。逆にL1キャッシュは2cycleとか信じられないくらい速いです。way数もInst/Data共にPOWER6の2倍です。

補足として、レジスタ数が64、レジスタ幅が128bit(SIMD共用)になりました。POWER6はレジスタ幅64bitで、整数、浮動小数、SIMDで独立でした。

一方疑問に思うのは、issueやdispatchが1スレッドあたり何命令なのか不明な点です。RISCアーキテクチャなのでx86より命令数を増やしやすいとはいえ、1スレッドで6命令もdispatchできるとは思えません。4スレッド(SMT-4)合計で6命令であって、1スレッド当たりでは最大3命令程度ではないでしょうか。

■Wii Uはどこまでスペック削減するか

オリジナルPower7のダイ面積は567 mm2、WiiUのCPU(Espresso)は 33 mm2です。NVIDIA Tegra2でさえ80 mm2なので(ただしGPU等を含む)、33 mm2というのは携帯電話用CPU並みの小ささです。同じ45nmプロセスルールなのにこれほど小さいということは、それだけ機能削減されているということです。

まず、L3キャッシュはおそらく省かれているか、2MB程度まで削減されているでしょう。GPU側の32MB eDRAMにアクセスできるという噂もある(ソースはAnandTech、XBOX360のCPUにも似た機能がある)ので、ない方に賭けます。eDRAMの面積は全体の4割程度だそうで、567×0.6≒340になります。

次に、8コアが3コアに減っています。340×(3/8)≒128。メモリコントローラやコア間通信等の面積を無視した超概算ですが、まだまだ全然足りません。

となると、コア内部の機能が削減されていると見るのが妥当です。Decimal Floatなどゲームに不要なものは削減されているでしょう。SIMD(VMX)もないと思います(Wikipediaによれば、32bit×2のFPU SIMDはあるらしい)。それでも足りるとは思えないので、FPUが4つから2つになったり、L2キャッシュが削られたりしているのかもしれません。

ちなみに、8コアPower7の消費電力は4.0GHzで200W超だそうです。どう考えても最大消費電力75WのWiiUには載せられません。そこで、コア数を8から3に減らし、クロックを1.24GHzという非常に低く押さえています。ダイ面積が1/18になっていることを考えると、もしかしたらWiiUのCPUは10W前後かもしれません。

ところで、「WiiUは1.24GHzだ!3.2GHzのXBOX360以下の産廃だ!」という2chスレッドが盛り上がっているようですが、Power7はIPCが改善されたので周波数だけの比較は意味がありません。実際IPC=6とすれば、XBOX360のIPC=2換算で3.72GHzとなり、XBOX360を上回ります(あくまで理論上の話です)。問題はPS3で、7コアあるSPU(SPE)の性能がPower7相当でどれだけになるのかちょっと想像がつきません。SPUの理論性能は(たぶん)IPC=1ですが、本気でチューニングすれば4-way SIMDで性能を稼ぐことができます。しかし、メモリ構成が独特(256kBスクラッチパッドメモリ)な点はマイナスになるので、わけがわからなくなります。

■PowerPC 750ベースでない可能性

ここまで書いてきてちゃぶ台を返すようですが、PowerPC 476FP 12Sベースの可能性もあります(最初に指摘したのはおそらく後藤さんです)。もっともこれもPower7ベースらしいのですが、組み込み機器向けで、1コア1.6GHz+で消費電力1.6W、3.6 mm2です。IPCは5に減らされており、Execution Unitも減っています。WiiU向けな気はするものの、3コアであることを勘定してもダイ面積が小さすぎて計算が合いません。

そもそもWiiUがPower7ベースであるというのは、IBMのWatsonのTwitterがソースなのですが、今確認したところ当該ツイートは削除されていました。

もしかすると、Power7とPowerPC 476FPの中間のようなCPUを新規開発したのかもしれません。

■GPUは本当にRadeon HD 4650/4670相当か

75Wという時点でGPUのTDPはせいぜい40~50W程度で、そこから考えて480コア程度かと個人的に予想していました。AnandTechによれば320か400コアだそうです。320コアならばRadeon HD 4650/4670(RV730)相当になります。

ダイ面積から妥当性を検証してみます。RV730は55nmプロセスで146 mm2です。WiiUのGPUは156 mm2なので近い値ではあります。しかし、RV730は55nmという古いプロセスで、現在AMDは40nmか28nmを使っています。もし40nmならば、RV730は100 mm2程度になるはずで、WiiUのGPUは少し大きすぎます。

考えられる一つの原因は、コア数が320より多いことです。AnandTechは”320 or 400″と書いており、400コアもありえると考えているようです。が、それでも100×(400/320)≒125でまだ足りません。余計な何かがあるような気がします。

2つ目の原因は、eDRAMを内蔵している可能性です。WiiUは32MBらしく、これはLSIとしては相当巨大です。が、この点は少し疑問があるので、考察は後にします。ちなみに、10MB eDRAMを搭載するXBOX360はeDRAM内蔵ではありません。PS3はそもそもeDRAMがありません。

3つ目は、そもそも40nmではなく55nmの可能性です。これならダイ面積の話は簡単ですが、40nmが手頃に使える今、生産コストが高くつく55nmを使うとは思えません。

次に、消費電力を考えます。600MHzのRadeon HD 4650は48Wです。40nmにシュリンクしたとすれば、40W弱くらいになりそうで、有り得なくはありません。

RV730世代というのは不思議ではないものの、どうもしっくりこない部分が残ります。

■本当にGPGPUできるの?

西川さんの記事で、Direct3D 10.1世代(Radeon HD 4000)であることが明かされています。

さて、任天堂のWiiUのプレゼンテーションで、岩田社長が「WiiUはGPGPUに対応する」と明言しました。

しかし、Radeon HD 4000系はOpenCL(GPGPUの一種)の性能が悪いそうです。どうやらRadeon HD 5000系にはあるLDS(Local Data Share、GeForceでいえばShared Memory)がないことが原因のようです。当然キャッシュなんていう生ぬるいものはありません。加えて、(説明は後述しますが)グローバルメモリの帯域が小さく、GPGPUとしては致命的に思えて仕方ありません。もしかして、eDRAM上でGPGPUしろということでしょうか。原理的に不可能ではないものの、それは(たぶん)過去に例がなく、プログラミングはなかなか難しいものになるでしょう。

PS3やXBOX360のGPUがDirect3D 9世代で、GPGPUが事実上不可能だったことから、WiiUのアピールポイントとして言っただけのような気がしなくもないです。あるいは最近のレンダリングテクニックでGPGPU(特にDirectX Compute Shader)を併用することが多くなってきたので、それを意識したのかもしれません。

■メモリ帯域の謎

スペックを調べて一番疑問に思ったのがメモリ帯域です。

任天堂のWiiUプレゼンテーションでグラフィックスメモリの話がなかったので、多分グラフィックスメモリなしのCPU/GPU統合メモリになると個人的に予想しました。しかも、任天堂はNINTENDO64の反省からCPU側のメモリのレイテンシを重視しており、XBOX360のようにGDDR3をメインメモリに使うことはないだろうとも思いました。

それは当たっているようで、DDR3-1600を使っているようですが、AnandTechによると16bit×4の64bit接続で、12.8GB/sしか出ないそうです。これはFull HDでないXBOX360やPS3以下です。どう考えても帯域が足りません。Full HD対応なのに720pのゲームしか作られなくなったPS3やXBOX360の悪夢がよみがえります。何かの間違いだと信じたいところです。

もうひとつの謎はeDRAMです。32MBという容量は巨大です。おそらくXBOX360と同じくルネサスエレクトロニクス製だと思いますが(MCMチップ開発にIBMとAMDとルネサスが関わっていると任天堂公式サイトに書かれています)、10MBしかないXBOX360のeDRAMでさえ45 mm2だそうで(ソース:後藤さんの記事)、32MBだと単純計算で144 mm2となり、そんな巨大なものはMCMチップの写真から見つけることができません。GPU統合説にしても、GPU自体が146 mm2しかないのに32MB eDRAMは載せられません。

DDR3メモリの帯域不足をeDRAMで補うアイデア自体は間違っていないし、12.8GB/sしかない帯域を補うにはeDRAM以外の方法はあり得ないはずです。

もしかすると32MBではなく16MBやそれ以下なのかもしれません。しかし、Full HDを謳うWiiUの解像度では、1920×1080ピクセルのRGBA 8bitレンダーバッファに8MB強必要で、FP16のHDRレンダリングを考えると16MBはギリギリ足りません。

あるいは、GPUのプロセスがTSMCの28nmという可能性です。これなら32MB eDRAMを混在して146 mm2というのは無理ではありません。しかし28nmは供給量不足状態なうえに、GPUとeDRAMの混在は簡単ではないので(混在した可能性が出てきたので消しました)、可能性としては低いと思います。

結局、eDRAMの件はどうもしっくりきません。

■まとめ

流出したスペックを検証?しました。謎の残った部分は、今後の追加情報待ちです。

■2013/2/23追記

eurogamerによると、GPUは320コア、16TMU、8ROPだそうです。8ROPは実はPS3のGPUと同じで、Wii Uゲームパッドには十分ですが、1080pのゲームは難しそうです。もっともeurogamerの記事が正しい保障はありませんが。

上の考察でダイ面積的にeDRAMがでかすぎるという話を書きましたが、Xbox360のeDRAMはMSAAやZテストなども出来てしまうらしく、その分のダイ面積がかなり大きいのかもしれません。もっとも単にルネサスのeDRAM技術・製造技術が上がっただけかもしれませんが。


AndroidのGLSurfaceViewにおけるOpenGL ES 1.0と1.1のひな形

$
0
0

とりあえずOpenGL ESで3Dのモデルを表示する時の手順です。AndroidのGLSurfaceViewを想定していますが、iOSでも参考になるかもしれません。

インデントがおかしいのはWordpressの仕様なので我慢してください。import文等は省略しています。

■GLSurfaceViewの作り方

public class MainActivity extends Activity {

 GLSurfaceView glView;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 //setContentView(R.layout.activity_main);

 glView = new GLSurfaceView(this);
 // デバッグ時には次のフラグを立てると自動でエラーチェックされる(ただし遅い)
 glView.setDebugFlags(GLSurfaceView.DEBUG_CHECK_GL_ERROR);
 // OpenGL ES 2.0互換のEGLを選択するときは次のようにする
 // 注意:AndroidManifestにuses-featureが必要
 //glView.setEGLContextClientVersion(2);

 glView.setRenderer(new GLTest(this));
 setContentView(glView);
 }

 @Override
 public void onResume() {
 super.onResume();
 glView.onResume();
 }

 @Override
 public void onPause() {
 super.onPause();
 glView.onPause();
 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
 getMenuInflater().inflate(R.menu.activity_main, menu);
 return true;
 }

}

■OpenGL ES 1.0

頂点バッファは1つだけです。1頂点ごとに座標とUV(厳密にはUVではなくST)が入っているものとします(調べた所、多くのサンプルは座標で1バッファ、UVで1バッファそれぞれ用意していますが、今時そのような使い方はあまりしないと思います)。法線やライティングはなしです。インデックスバッファを使っています(トライアングルリスト)。マテリアルはテクスチャ以外無視します(テクスチャも要らなければnullにすればとりあえず動きます)。

8千頂点、1.5万面(4.5万ポリゴン)のとある3Dモデルを動かしました(残念ながら借り物なので著作権上公開できません)。

class GLTest implements GLSurfaceView.Renderer {

 int winWidth_;
 int winHeight_;

 Activity act_; // リソースの読み込みに使うアクティビティ
 int[] texID_; // テクスチャID
 FloatBuffer modelVtx_; // 頂点バッファ
 ShortBuffer modelIdx_; // インデックスバッファ

 GLTest(Activity act) {
 act_ = act;
 InputStream is = act.getResources().openRawResource(R); // モデルデータ読み込み
 // 頂点バッファをmodelVtx_に、インデックスバッファをmodelIdx_に格納
 // 各バッファはByteBuffer.allocateDirect([バイト数]).as***Buffer()で生成する
 }

 @Override
 public void onDrawFrame(GL10 gl) {
 int glerr = GL10.GL_NO_ERROR;

 // モデル・ビュー変換
 gl.glMatrixMode(GL10.GL_MODELVIEW);
 gl.glLoadIdentity();
 GLU.gluLookAt(gl, 0, 0, -20, 0, 0, 0, 0, 1, 0); // 視点の指定

 // 射影変換
 gl.glMatrixMode(GL10.GL_PROJECTION);
 gl.glLoadIdentity();
 GLU.gluPerspective(
 gl, 45.0f,
 (float)winWidth_ / winHeight_, 0.2f, 120.0f); // 透視変換の指定

 // ビューポート
 gl.glViewport(0, 0, winWidth, winHeight);

 // レンダーターゲットのクリア
 gl.glClearColor(0.1f, 0.2f, 0.4f, 1.0f);
 gl.glClear(
 GL10.GL_DEPTH_BUFFER_BIT | GL10.GL_STENCIL_BUFFER_BIT
 | GL10.GL_COLOR_BUFFER_BIT);

 // (必要に応じて)カリングの指定(有効のほうが好ましい)
 gl.glDisable(GL10.GL_CULL_FACE);
 //gl.glFrontFace(GL10.GL_CCW);
 //gl.glCullFace(GL10.GL_BACK);

 // 深度バッファの有効・無効指定
 gl.glEnable(GL10.GL_DEPTH_TEST);

 // (必要に応じて)アルファブレンドの指定(無効のほうが好ましい)
 //gl.glEnable(GL10.GL_ALPHA);

 // テクスチャの有効・無効指定
 gl.glEnable(GL10.GL_TEXTURE_2D);

 // UV座標配列と頂点座標配列を有効化
 gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

 // UV座標配列の指定
 //gl.glActiveTexture(GL10.GL_TEXTURE0);
 gl.glBindTexture(GL10.GL_TEXTURE_2D, texID_[0]);
 modelVtx_.position(3); // UVが頂点バッファのどの要素番号から始まるかを指定
 gl.glTexCoordPointer(2, GL10.GL_FLOAT, STRIDE, modelVtx_); // STRIDEは1頂点あたりのバイト数

 // 頂点座標配列の指定
 modelVtx_.position(0); // 座標が頂点バッファのどの要素番号から始まるかを指定
 gl.glVertexPointer(3, GL10.GL_FLOAT, STRIDE, modelVtx_);

 // インデックスバッファの指定
 modelIdx_.position(0);
 gl.glDrawElements(
 GL10.GL_TRIANGLES, modelIdx_.limit(),
 GL10.GL_UNSIGNED_SHORT, modelIdx_);

 // コマンドのフラッシュとエラーチェック
 gl.glFlush();
 if((glerr = gl.glGetError()) != GL10.GL_NO_ERROR) {
 String msg = "OpenGLでエラー@onDrawFrame : " + glerr;
 Log.e("GLTest", msg);
 }
 }

 @Override
 public void onSurfaceChanged(GL10 gl, int width, int height) {
 winWidth_ = width;
 winHeight_ = height;
 }

 @Override
 public void onSurfaceCreated(GL10 gl, EGLConfig config) {
 int glerr = GL10.GL_NO_ERROR;

 // テクスチャの読み込み
 Bitmap bmp = BitmapFactory.decodeResource(act_.getResources(), R);
 texID_ = new int[1];
 gl.glGenTextures(texID_.length, texID_, 0);
 gl.glBindTexture(GL10.GL_TEXTURE_2D, texID_[0]);
 GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);

 // エラーチェック
 if((glerr = gl.glGetError()) != GL10.GL_NO_ERROR) {
 String msg = "OpenGLでエラー@onSurfaceCreated : " + glerr;
 Log.e("GLTest", msg);
 }
 }
}

■OpenGL ES 1.1

頂点バッファオブジェクト(VBO)とインデックスバッファオブジェクト(OpenGLでの正式な言い方が分からないorz)を使います。インデックスバッファはOpenGLではElelemt Array Bufferというらしいです。

class GLTest implements GLSurfaceView.Renderer {

 int winWidth_;
 int winHeight_;

 Activity act_;
 int[] vboID_; // VBO
 int[] iboID_; // インデックスバッファ
 int[] texID_;
 FloatBuffer modelVtx_;
 ShortBuffer modelIdx_;

 GLTest(Activity act) {
 // モデル読み込みは同じなので省略
 }

 @Override
 public void onDrawFrame(GL10 gl) {
 int glerr = GL10.GL_NO_ERROR;
 GL11 gl11 = (GL11)gl; // OpenGL ES 1.1 APIを使う

 // 座標変換や初期化は同じなので省略

 // UV座標配列の代わりにVBOを指定
 gl.glBindTexture(GL10.GL_TEXTURE_2D, texID_[0]);
 gl11.glTexCoordPointer(2, GL10.GL_FLOAT, PmdReader.PMD_VERTEX_STRIDE, 4 * 3);

 // 頂点座標配列の代わりにVBOを指定
 gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, vboID_[0]);
 gl11.glVertexPointer(3, GL10.GL_FLOAT, PmdReader.PMD_VERTEX_STRIDE, 0);

 // インデックスバッファの指定
 gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, iboID_[0]);
 gl11.glDrawElements(
 GL10.GL_TRIANGLES, modelIdx_.limit(),
 GL10.GL_UNSIGNED_SHORT, 0);

 gl.glFlush();
 if((glerr = gl.glGetError()) != GL10.GL_NO_ERROR) {
 String msg = "OpenGLでエラー@onDrawFrame : " + glerr;
 Log.e("GLTest", msg);
 }
 }

 @Override
 public void onSurfaceChanged(GL10 gl, int width, int height) {
 winWidth_ = width;
 winHeight_ = height;
 }

 @Override
 public void onSurfaceCreated(GL10 gl, EGLConfig config) {
 int glerr = GL10.GL_NO_ERROR;
 GL11 gl11 = null;

 // OpenGL ES 1.1をサポートしていない環境を弾く
 if(!(gl instanceof GL11)) {
 throw new UnsupportedOperationException("OpenGL ES 1.1 cannot use");
 }
 gl11 = (GL11)gl;

 // VBOを作る
 vboID_ = new int[1];
 gl11.glGenBuffers(1, vboID_, 0);
 gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, vboID_[0]);
 gl11.glBufferData(
 GL11.GL_ARRAY_BUFFER, 4 * modelVtx_.limit(),
 modelVtx_, GL11.GL_STATIC_DRAW);

 // インデックスバッファを作る
 iboID_ = new int[1];
 gl11.glGenBuffers(1, iboID_, 0);
 gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, iboID_[0]);
 gl11.glBufferData(
 GL11.GL_ELEMENT_ARRAY_BUFFER, 2 * modelIdx_.limit(),
 modelIdx_, GL11.GL_STATIC_DRAW);

 // テクスチャ作成は同じなので省略

 if((glerr = gl.glGetError()) != GL10.GL_NO_ERROR) {
 String msg = "OpenGLでエラー@onSurfaceCreated : " + glerr;
 Log.e("GLTest", msg);
 }
 }
}

■VBOを使う利点

  1. 速い(噂では3割速い)
  2. Bufferのpositionをいちいち変更しなくていい

■ハマったところ

  1. モデルデータがバイナリ形式のとき、エンディアン(バイトオーダ)を合わせなければならない(ByteBuffer.order()で明示的にフォーマットのエンディアンを指定することで自動的に変換してくれる)
  2. ByteBufferはダイレクトバッファでなければならない。さもなくばOpenGLにデータが渡されない(allocateDirect()必須)
  3. ByteBufferにputなりwriteなりで書き終えたら、flip()で終点をマークしてポインタを先頭に戻さなければならない(rewind()やposition(0)でもよいが、終点マークはされない(らしい))
  4. 引数の単位を合わせる。度orラジアン、バイト数or要素数など(基本的には、OpenGLは度とバイト数、Bufferは要素数)

なお、この後別のモデルを表示したいときは、必要に応じてglBindBufferでバインドしたオブジェクトを解放してください(glBindBufferの第2引数に0を指定)。

ところで、GLSurfaceViewではglDeleteTexturesとかglDeleteBuffersとかは要らないんでしょうかね?


【メモ】技術系Advent Calender 2012の個人的お気に入り記事

$
0
0

2012年度に行われた技術系Advent Calenderで、個人的に興味深い・役に立つ記事をまとめました。99%個人用です。1%の気の合う他人のために公開します。説明文は適当なので気にしないでください(とにかく有用な情報へリンクして残しておくことが第一ミッション)。

分野が偏っているので注意。面白い記事が沢山あるのですが、私の頭がついていかなかったものも多数多数多数あります。ぜひ時間があれば、各Advent Calenderの全記事を回っていただければと思います。

俺の記事がねぇぞゴルァ、という苦情はご遠慮ください。1000を超えるAdvent Calenderの記事を全部紹介するのは無理です。

本家Advent Calenderは12/25で終わりらしいのでもう公開しますが、まだ続いているAdvent Calenderもあるので今後更新する予定です →更新しました)

Android Advent Calender

☆Android端末-PC間 USBケーブルによる通信
adbのforwardコマンドで超簡単にAndroidと通信できる話

☆Androidでとびきりうざい アプリを作ってみる
オーバーレイで常に画面の最上位に表示させる方法。WindowManager.LayoutParams.TYPE_SYSTEM_ALERTがミソ。AndroidのViewの仕組みの図もあって分かりやすい(でも身代金要求型ウィルスが簡単に作れてしまうな…)

☆Android 開発者が読んでおくべき6つの記事
Androidプログラミング中級者向け。非常に有用な記事6つの紹介。

☆Googleアカウントでのサービス認可周りの紹介(OAuth2.0とか Google Play Servicesとか Cloud Endpointsとか)
IMEIとかAndroid IDとかガラパゴスで危険な認証方式は即刻止めよう。

JellyBeanの新しいAPIを試してみる(MediaCodecと外部ディスプレイ)
Android 4.2から自前コーデックと2画面?がサポートされたので実験したという記事。コーデックは面白そう、特にMX動画プレイヤーにお世話になっている人は

Android Design 実装してみた(Patterns – Multi-pane Layouts)
読んでおくべき6つの記事と少し関連しているけども、Fragmentの使い方など。最近この手のレイアウトのアプリが多い気がする

世界の中心でGoogle Maps Android API v2に喝采を送る
サービス認可周りの紹介に関連して、Google Map API周りのv2におけるポイントの紹介

自作のUSBデバイスを、Androidで動かす
PCでいえばUSBホストドライバ相当のものを作る方法。個人的にすごく興味がある

drawable.xmlで遊んでみる
リソースファイルでドロイド君を書く方法。もはや職人技

■ひとりAndroid Advent Calendar

データの暗号化、camellia-androidを試す
使い方がよくわからないけどメモ。SDカードにプライベートなデータを安全に保存したいときに使えるかもしれない。リンク先のPDFにNTTによるアルゴリズムの解説あり

WebView使わずに、twitter4j のOAuth認証
私もWebViewで認証する方法はセキュリティ的に問題があると考えているので(みんな楽したがるけど…)、この実装方法はおすすめ

Push通知、GCM(Google Cloud Messaging)を試す。複数端末に送信
RecognizerIntent、アプリから音声認識する
タイトル通り

C# Advent Calender

☆.NET Framework4.5 での非同期I/O処理 事始め
C# 5.0(.NET Framework 4.5)からasyncとawaitキーワードで非同期処理が非常に簡単に書けるという話。Windows RTには必須の知識。

IEnumerableの型を指定したforeach
ジェネリクスでないIEnumerableは型を宣言すると便利という話

クラスのインターフェースに使うコレクションのinterface使い分け
ややこしい…あとで読む

C#でログファイルを出力する少し冴えたやり方
RazorテンプレートエンジンでPHPやJSPっぽい書き方をする方法

C++ Advent Calendar 2012

☆C++ Advent Calendar 2012 「18日 : Cer に知って欲しい C++」
vector、accumulate、shared_ptr/unique_ptrの使い方。Cerというより、「C++をちょっとかじっただけの自称C++erに知ってほしいC++」かも。個人的にはunique_ptrにとてもお世話になっている

☆ゲームプログラミングにおけるC++の都市伝説
テンプレートすごい(速い)とは聞いていたけど、本当にすごい

構造化『並列』プログラミング
基本的なアルゴリズムを並列化するためのアイデアとTBBを使った実装。一部ラムダ式の知識が必要

Computer Vision Advent Calendar 2012

☆NativeViewerの使い方
VisualStudio 2010/2012でOpenCVのcv::Matの中身をimshowせずに確認するプラグインの紹介。これは便利。

文献紹介: Siggraph2012 High quality Image Deblurring with Panchromatic Pixels
デジカメのセンサに当たり前のように使われているBayerパターンを改良し、より高精度なセンサを作るためのアイデア。RGB以外に白を入れるという発想が面白い。

英語のオンラインクラスで学ぶコンピュータビジョン
ネットで勉強するCV。かなりレベル高そうだけど、相当価値が高そう

ジョイントバイラテラルアップサンプリング
私には理解できない(というかバイラテラルが何か自体分かっていない)けどとにかくすごい。ソースつき

コンシューマデプスセンサの比較
最近熱い深度センサの種類分けと紹介。近未来感のある記事

iOSでのリアルタイム動画処理
カメラの画像にフィルタを掛けてリアルタイム表示

Garbage Collection Advent Calendar 2012

Dart VMのGC概要
世代別GC(とMark&Sweepアルゴリズム)がお決まりになりつつあることを再確認

Git Advent Calendar 2012

git push の反対は git pull ではない
git fetchだそうで。知らなかった

GPGPU Advent Calendar

thrustで3引数以上のtransformを実行する方法
別の研究室のT君がthrustで困っていたのでメモ

☆CUDA プロファイラを使う
CUDA Visual ProfilerではなくCUIでカウンタを見る方法と、命令数やIPCの数え方、おまけでCUPTIの使い方。CUDAのプロファイラカウンタって項目毎の説明が曖昧で分かりにくくて困る

Curl Noise with OpenCL
カールノイズのGPGPUコード。Agniでも使われたらしい。Perlin Nozeしか知らなかったので後で勉強する

GPUでナップザック問題を解く話 GPGPU AdC2012編
thrustも使っていてちょっと複雑だけど、CPUコードつきなのでなんとなくわかる

☆ARMのOpenCL(GPGPU)対応メモ
ええー!Adreno 320以降だと、もうOpenCL動くの!?Adreno SDKさえあればいいみたい。これは夢が広がる

gpu_profiler_counter
CUDA Profilerを使うに続き、プロファイラの読み方。inst_issued2_1/2は2倍しないと駄目らしい

Intel HD Graphics 4000 とは何だったのか
Intel GPUの仕組みの紹介。MMUとかバッチとかEUとかハードウェアを直接弄るような情報ばかりで貴重

Machine Learning Advent Calendar 2012

ABテストのための有意性検定
「検定」により有意かどうか判定する方法の解説。R言語を知らなくても理屈は分かるのでおすすめ

パラメトリックとノンパラメトリックの狭間
データの関係性を推定する2つの方法の解説。ガウス過程以降が難しくて理解できないけど(機械学習の世界では超基本らしいです。私は講義取らなかったので分からない…)、パラメトリック推定は分かりやすい

☆Computer Visionで用いられている機械学習の概観
これはすごい。いわゆるサーベイ?コンピュータビジョン入門向け。大学の講義で使ってほしいくらい

文字コードの自動判別を機械学習で
実用的ではないとはいえ、機械学習で文字コード判定という着眼点にまず驚き。そして精度が非常に高いこと(nkfにわずかに劣る程度)にさらに驚き。

Objective-C Advent Calendar

Linq for Objective-Cでお手軽シーケンス処理
同じ作者のLinq for Objective-Cを使って、iOSアプリで.NET FrameworkのLINQと似た構文を書けるようにする方法

Objective-Cでよく使う便利マクロを10個集めてみた
確かに便利そう(でもMacないので試せない)

OpenCV for iOSの使い方
林檎製品買ったら真っ先にやろうと思っていたのでメモ。意外にもAndroidのチュートリアルはたくさんあるのにiOSはあまり見ないので貴重(まじめに探していないだけかもしれない)

Objective-Cでドット繋ぎでメソッドチェインを行う
Objective-C勉強中なのでメモ

Perl Advent Calendar Japan 2012 Casual Track

Dropbox上のMarkdownテキストをプレビューしちゃえ!
Text::MarkdownとWebService::Dropboxを組み合わせるテクニック。いつの間にかなんでもモジュール化されるPerlらしさ溢れる記事。

☆こんなマジック知らなかった。
Variable::Magicモジュールで変数の変更と参照の瞬間をキャプチャできるという便利なhack

PHPのアプリだけどperlでテストするんだぜ?(ワイルドだry
PerlからApacheを立ち上げてテストとベンチマークもしてしまう方法。モジュールがいっぱい出てきてよくわからないけど、なんかすごい

☆PDLで数値計算
Perlで使える行列ライブラリ?Eigenとかと同類かもしれない。最後は画像処理まで出てきて、まるでcv::Matみたいになっている。ちなみに私も落陽草の花回収中にリオレイアに襲われます

PHP Advent Calender 2012

PHPを使う理由
個人的に激しく同意だったのでメモ

Raspberry Pi でPHPを動かしてみた
Raspberry Piという超小型PCでPHPのサーバが動いたという話。すごく欲しい

php5.5で追加された機能を触ってみる
yield、foreach内のlist、finally

似てるけど似てないシリーズ
echo/print、print_r/car_dump、シングルクオート/ダブルクオート、&&/and。最後の&&/andは、Perlでよくある”open *** or die”の”or”と同じ意味と考えれば理解できるかも

PHPerのMVCの一体どこが間違っていたのか
むしろMVCを意識したプログラミングをこれからする人の方に有用かもしれない(わたしです)

Visual Studio Advent Calendar 2012

☆Visual Studio Professional以上で利用できる機能と愛用しているショートカット
一押しショートカットが本当に便利すぎる

☆Git Source Control Providerの使い方
Git勉強中なのでメモ

☆コードスニペットを使ってみよう!
Tabキーを押すなんて知らなかった…

Web Music Developers JP Advent Calendar 2012

WebMidiLinkで遊んでみた
これはすごい。ブラウザでMIDIが演奏できる(Firefoxで確認)。音色はPSGとPCM音源の組み合わせっぽい?携帯電話の音源チップっぽい音。CPU負荷が半端ないのはJavaScriptだから仕方ないか

簡単な式で波形生成してみる
基本波形と三角関数の近似(テイラー展開の誤差の補正)

Web Audio系APIを使うときに注意する点
ブラウザで波形生成して鳴らすにはWeb Audio系(ChromeやSafariなどのWebKit採用ブラウザ)とAudio Data系(Firefox)があって、その両方の注意点について

■新人/若手向け、これだけは知っとけTips25 Advent Calendar 2012

☆作業効率化の時短ショートカットを厳選紹介
ほとんど知っていたけど、エクスプローラの「Alt+→」「Alt+↑」は目から鱗。知っておいて損はない。ちなみに戻るは「BackSpace」派(Alt押すの面倒)。

ちょっと楽になるviの操作
大学時代の実験でviの操作がさっぱりわからず苦労したのでメモ

新人から始めるノートの取り方について
これから必要になりそうなのでメモ

■(Advent Calenderとは一切関係ないけどメモしておきたい最近の記事)

プログラマーが知っておくべきうつ病の知識
同僚・知人がうつ病になったとき、周囲が適切な対応をとる必要があるという意味で、まさに知っておくべき知識。うつ病は誰でもなります(私はしょっちゅうです…)。「トリプルカラム法」が気になる

☆優先順位付き大小比較
C++ではstd::tieするだけっていう恐ろしいほどの簡単さ。Cではどうやっても無理

論文作成の技法part1~論文の構造
演繹法、帰納法、弁証法、仮説検証、IMRAD

ソーシャルゲームの予算規模を軽くまとめる
生々しい。書籍にまとめて出版してほしい

■(もはや完全自分向け)

さらばギザギザ! NVIDIAがアンチエイリアスを技術解説
2ページ目の「MSAAでは極端に輝度の高い(High Dynamic Range)レンダリングではどうしてもエイリアシングが現れてしまう」がどうも理解できない。HDRのMSAAでは高輝度に引っ張られるので単純平均ではダメということは分かるけど、ガウス関数による補正が単純平均より物理的に正しい理由って何

西川善司の3Dゲームファンのための「AGNI’S PHILOSOPHY」講座
[SQEXOC 2012]FFXIVで使われているAI技術~敵NPCはどうやって経路を探索しているのか?
第1回 スクウェア・エニックス オープンカンファレンス資料公開ページ
USTREAM: SQUARE-ENIX-OpenConference(タイムシフト?)
スクエニのAgni関連記事。コンシューマゲームで一番熱い話題だと思う。個人的に印象に残ったのは、犬のモーションキャプチャ

視神経モデル網膜シミュレーション -Retina simulation of Human Visual System-
3DCGで網膜シミュレーションによるリアルな見せ方をするためのアイデア。実装が非公開なのが残念

OpenGCD
AppleのGrand Central DispatchをAndroidやWindowsで動かすライブラリ。多分libpthreadのglue

Objective-Cプログラミング言語(PDF注意)
Objective-Cプログラミングの概念(PDF注意)
ジョブズ教に入るために必須

【画像】これを見てもアニメキャラは日本人って言い切れるかい?
日本人ェ…

■さいごに

すべてのAdvent Calenderのライターさんに感謝します。ありがとうございました。そしてお疲れ様です。来年も期待しています。


2013年に登場するSoCの性能比較

$
0
0

CES2013で発表されたスマートフォン・タブレット向けSoCの性能を比較しました。

一部2012年発表のものもありますが、量産が2013年ということで許してください。

【おわび】

ARMのGPUである”Mali”が全部”Mail”になっています。誤表記です。暇なときに直します。

Tegra4

Snapdragon 800

Exynos 5450

K3U3

MT6589

Temash

Atom Z2580

メーカー

NVIDIA

Qualcomm

Samsung

Huawei

MediaTek

AMD

Intel

製造

TSMC 28nm HPM

TSMC 28nm HPM

Samsung 28nm

TSMC 28nm

28nm

Intel 32nm SoC

CPU命令セット

ARMv7

ARMv7

ARMv7

ARMv7

ARMv7

x86

x86

FPU命令セット

VFPv4

VFPv4

VFP4

VFPv4

VFPv4

AVX

SSSE3

CPU

Cortex-A15

Krait 400

Cortex-A15

Cortex-A15

Cortex-A7

Jaguar

Clover Trail+

命令スケジューリング

OoO

OoO

OoO

OoO

In Order

OoO

In Order

IPC

3

3(4issue)

3

3

2

2

CPUコア数

4

4

4

4

4

4

2(論理4

電力抑制コア

1

4Cortex-A7

0

0

0

CPU標準周波数

1.2GHz

1.3GHz

CPU最高周波数

2.1GHz

1.8GHz

1.5GHz

NA

1.8GHz

FPU SIMD

128bit

128bit

128bit

128bit

64bit

128bit

CPU L0キャッシュ

NA

4kB+4kB

1way+1way

NA

NA

NA

NA

NA

L1キャッシュ

32kB+32kB

2way+2way

16kB+16kB

4way+4way

32kB+32kB

2way+2way

32kB+32kB

2way+2way

32kB+32kB

2way+4way

32kB(I)+24kB(D)

8way+6way

CPU L2キャッシュ

8way

2MB

8way

2MB

16way

16way

1MB

8way

2MB

1MB

8way

メモリ

LPDDR2

LPDDR3

DDR3L

LPDDR3-1600 (800MHz)

LPDDR3-1600

DDR3-1600

LPDDR

LPDDR2

DDR3L-1066

DDR3U-1066

メモリバス

64bit

64bit

64bit

64bit

64bit

64bit

メモリ帯域

12.8GB/s

12.8GB/s

17.1GB/s

GPU

ULP GeForce

Adreno 330

Mail-T678

Vivante?

PowerVR SGX544

Radeon

PowerVR SGX 544

GPUコア数

72

コアの概念なし

16?

1

2

ユニファイドシェーダ

No

24V48P

Yes

Yes

Yes?

Yes

Yes

Yes

レンダリング方式

IMR

TBR/IMR(切り替え)

TBR

TBDR

IMR

TBDR

Direct3D機能レベル

9 level1

9 level3

9 level3

9 level3

11.1

9 level3

OpenGL ES

(「我々は最良の選択をした」)

3.0

3.0

2.0

2.0

OpenCL

1.2

1.1 FP

NA

NA

GPU周波数

320MHz

533MHz

動画デコード

1440p

30fps@4K

30fps@1080p

動画エンコード

1440p

30fps@4K

30fps@1080p

VP8コーデック

対応

ネットワーク

LTE

IEEE 802.11n

i500外付け)

LTE

IEEE 802.11ac

Bluetooth 3.1

(内蔵)

3G

3G

IEEE 802.11n

Bluetooth

MT6628外付け)

LTE

XMM7160外付け?)

SoC TDP

5.9W

【補足】

?マークつきの記載は予測です。基本的に1世代前のものを参考にしています。NAはNot Available(非対応)の略です。OoOはOut-of-Orderの略です。

Huawei K3V3は自信がありません。K3V2についてはGPUは16コアという公式情報しかありませんが、Huawei D2-5000のGLBenchmarkのGL_EXTENSIONSにGL_VIV_timestampやGL_VIV_shader_binaryがあることからVivante GC4000であると考えられ(インチキな数え方をしない限り16コアと言っている時点でVivanteしかありえないのですが)、K3V3は同等かその後継GPUを搭載するはずだと考えて記入しました。

MediaTekのGPUのコア数・クロックは、画像検索で頂点55M/s・ピクセル1600M/sと書いてあったので、1コア時の性能(32M/s・1000M/s@200MHz)から計算して求めました。

Cortex-A15 SoCの設計中止がほぼ決まったTIとルネサスエレクトロニクスに黙祷。あとは中華SoCがどこまで出てくるか。

【追記】

しまった、中華SoCのRockchip RK3188を書き忘れた。

4core Cortex-A9 1.8-2.0?GHz Mail-400(4core, 500?/533?MHz) OpenGLES2.0 60fps@1080p(decode) 30fps@1080p(encode) VP8 suport 28nm HKMG(TSMC 28nm HPM?) 4G

【追記2】

Allwinner A10/A13の後続品も発表されているらしい(いつの間に?)。下のWikiが詳しい。

Allwinner A31 4core Cortex-A7 1.0GHz? L2 1MB LPDDR2/DDR3/DDR3L 64bit PowerVR SGX544MP2(OpenGL ES 2.0, OpenCL 1.x, Direct3D 9level3) 30fps@2160p(decode) 60fps@1080p(encode) TSMC 40nm

Allwinner A20 2core Cortex-A7 L2 512kB LDDR2/DDR3/DDR3L 32bit? Mail-400(2core) 2160p(decode) 60fps@1080p(encode) TSMC 40nm

Allwinner A10s 1core Cortex-A8 L2 256kB DDR2/DDR3 16/32bit Mail-400(1core) 30fps@1080p(decode/encode) VP6/VP8 support TSMC 40?/55?nm

参考:AllWinner Publishes A31 and A20 Processors Details

【あわせてよみたい】

中華padで使われるCPUのメモ 2012/05/08版

【情報源】

Google先生の検索トップ20(公式発表前の予測は除外)

日本語・英語Wikipedia(うさんくさい情報は主観で除外)

PC watch、4gamer、engadget、AnandTech、Tom’s hardwareなどのニュースサイト

ARM Cortex-A15 – 7-cpu

Cortex-A15 MPCore Technical Reference Manual - Components of the processor

その他たくさん

【さいごに】

論文やばい


PlayStation 4 スペック

$
0
0

本日PlayStation4 (PS4) が発表になりましたが、断片的にスペックの情報が出てきたのでまとめました。

ソース:「プレイステーション 4」発表

【重要】情報の信頼性は保証しません。

■CPU

AMD Jaguar (AMD64 ISA)

8core

■GPU

(CPUと統合されたシングルチップ)

AMD next-generation Radeon based graphics engine

1.84TFLOPS

18 Compute Unit

GPGPU Ready

■メモリ

8GB

GDDR5

176GB/s

CPU・GPU共用

■GPUはRadeon HD 7850に近い

GPUのスペックが予想以上に詳細に公開されました。

まず、next-generation Radeonと書いてあることから、GCNアーキテクチャ(Radeon HD 7xxx以降)であることが分かります。倍精度浮動小数演算などは省略されている可能性があります。

次に、18 Compute Unitと書いてあることから、1152コアであることが分かります。計算式は「16(Vector Unit)×4×18(Compute Unit)=1152」です。Radeon HD 7850が1024コア、7870が1280コアなので、その中間ということになります。歩留りの関係でこんな中途半端な数になったのでしょう。

そして、コア数とFLOPS値(演算能力の指標)からクロック数を求めると、0.799 GHzであることが分かります。計算式は「1.84(FLOPS)÷1152(コア)÷2(MAD/cycle)=0.799」です。800 MHzと見て間違いないでしょう。Radeon HD 7850が860MHz、7870が1GHzなので、それより遅いです。クロックを上げると電圧も上げなければならず、電圧は消費電力に大きく影響するため、あえて抑えているのでしょう。

Radeon HD 7850は1.76TFLOPS、7870は2.56TFSLOPSなので、PS4のGPUはRadeon HD 7850程度の浮動小数点演算性能を持っているといえるでしょう。ちなみに、Radeon HD 7850のTDPは130Wなので、映像出力やメモリを除いたGPU単体での消費電力は100W程度だと思われます。

テクスチャフェッチ、テセレーション、ROPの性能がどうなるかは不明です。7850から大きく変わることはないとは思いますが。

上のPDFによると、PS4のGPUはGPGPUのサポートしており、大規模なSIMD演算はGPUにやらせることができます(GCNなのでGPGPUに対応していて当然なのですが)。Wii UのGPU(Radeon HD 4xxx)もGPGPUをサポートしており(CPUとGPUがメモリ空間を共有している点もPS4と一致)、今後の据え置きゲーム機ではGPGPUが流行るかもしれません。

■CPUはAMDの新アーキテクチャ”Jaguar”ベース

現在ISSCCも開催されており、タイミングよく昨日くらいにJaguarアーキテクチャの講演がありました(記事待ちです…)。Jaguarは、AMD E-350などに代表されるモバイル向けPCやタブレットに搭載されているBobcatアーキテクチャの後継です。

参考:AMDが次世代CPUコア「Steamroller」と「Jaguar」の概要を発表

Bobcatの特徴は、アウトオブーオーダ実行で2命令デコードです。2コア・1.6GHzで消費電力18Wです(80コアのGPUを含む)。ピーク性能は低いものの、複雑な命令を実行しても性能が極端に落ちないという特徴があります。シングルスレッド性能はIntel Coreシリーズより遅くIntel Atomより速い程度です。詳細は4gamerや大原さんの記事を参考にしてください。

JaguarはBobcatの弱点を改良しています。SIMD(SSE)が64bit幅から128bit幅になり、拡張命令が増え(SSE4.2、AVX、AES-NI、MOVBE、F16Cなど)、L1キャッシュの帯域が8byte/cycleから16byte/cycleになり、整数除算器を搭載しました。一般市場向けのJaguarコアは4コアまでしか搭載されないことが明らかにされていますが、AMDはPS4のために8コアへ拡張したようです(例によってうち1コアはOS占有でしょう)。

分かっていることはこれくらいなので、以下は想像です。

2コアのBobcatのCPU部のTDPは8W前後だそうです。8コアだと単純計算で32Wになります。PS4にカスタマイズされているとはいえ、PS3のCellプロセッサに比べれば大人しいものに仕上がりそうです。個人的には、爆熱として黒歴史になりつつあるBulldozerベースにならなくて良かったと思います。

今のところJaguarのクロックは不明です。しかし、Jaguarと同じく製造プロセスがTSMC 40nmからTSMC 28nm HKMGになったNVIDIA Tegra3/Tegra4のCPU(Cortex-A9/Cortex-A15)の場合、1.6GHzから1.9GHzに上がっています。また、Qualcomm Snapdragon 800は28nmで2.3GHzの予定です。モバイル向けCPUでは2GHz前後に落ち着くようなので、電力の制限が比較的小さいPS4のCPUなら2GHzは超えると思われます。GPUが0.8GHzなので、キリの良い1.6GHzか2.4GHz、3.2GHzではないでしょうか(さすがに3.2GHzはパイプライン段数を増やさないと駄目な気がしますが)。

■メモリは256bit・1.375GHz

メモリのアーキテクチャは、AMDのAPUのメモリアーキテクチャをGDDR5に対応させたもののように思えます(直感)。XBOX360やWii UがやっているようなeDRAMの話は全く出てきておらず、どうやらなさそうです。

参考:AMDの「AシリーズAPU(Llano)」の内部バスアーキテクチャ

メモリコントローラの情報がないので断定できませんが、256 bit接続で1375 MHz5.5 Gbps)だと思われます。「256(bit)÷8(bit/byte)×5.5(Gbps)=176」なので、計算は合います。Radeon HD 7870(256bit・1200MHzで153.6GB/s)よりちょっと速い数字ですが、CPUの消費する帯域も考えれば妥当な構成です。

176GB/sという数字は、据え置きゲーム機の中ではトップになりますが、単体GPUとして見るとそれほど驚く数字ではありません。例えば、Radeon HD 7970の帯域は264GB/sです。

GDDR系列のメモリは、DDR系列のメモリに比べてレイテンシ(遅延)が大きいそうです。遅延はグラフィック処理ではそれほど問題になりませんが、CPUにとっては大問題です。これを隠蔽するには、大容量のキャッシュを搭載する必要があります。Jaguarは2コアで1MBのL2キャッシュを持つので、8コアなら単純計算で4MBになりますが、もしかしたらもっと増やされるかもしれません。

■PlayStation 4 Eye

という周辺機器が出たそうです

PlayStation Eyeとの大きな違いは、センサが2つある点です。ステレオカメラになっており、奥行きを推定することができます。画像処理はソニーの得意分野ではありますが、Kinectの後だし感があるのが惜しいです(Kinectは赤外線照射による奥行推定)。ただし、Kinectよりフレームレートが高いです。

また、音源位置推定のため4つのマイクアレイを搭載します。これもKinectと同じです。

画像を見た感じでは、チルトモーターを内蔵しているようです。これもKi(ry

■感想

PS3の時ほどピーク性能を求めていない印象です。特に8GBメモリなど、プログラマを泣かせない仕様に思えます。

最後にほぼ確定情報をもう一度まとめておきます。

GPU : GCNベース 1152コア 800MHz(Radeon HD 7850に近い)

メモリ:256bit 1.375GHz

■3/2追記

Vgleaksによると、CPUのL2キャッシュは4MBで、4コアで2MBを共有したものを2つ持つようです。Jaguarコアは4コアまでしか想定していないので、ノースブリッジ経由でコヒーレンシを取る形で(Core2 Quadのように強引に)8コア搭載したようです。その結果、別ダイのCPU上にあるL2キャッシュ上のデータへのアクセスが約100クロックと、非常に膨大な遅延を起こしています。データ並列処理のためにマルチスレッドにする場合は4コアで止めるなど、(ヘテロジニアスな)CellのSPUと(シンメトリックな)XBOX360 CPUの中間のアプローチが必要になりそうです。

クロックは1.6GHzです。

2命令デコード、ROBは64、汎用レジスタのための物理レジスタファイルが64(128bit SIMDは72)、投機実行に対応、ストアフォアワーディングに対応、リターンスタックが16、”Out-of-page address predictor”が32です。

Vgleaksの情報が正しいとは限りませんが、非現実的でない構成ではあります。



GeForce GTX Titanの性能

$
0
0

GK110アーキテクチャのGTX Titanのスペックやベンチマークを調べ、GTX680(GK104)やRadeon HD 7970(GCN)と比較しました。

【重要】情報の信頼性は保証しません。

【注意】GK110はGeForce GTX TitanやTesla K20Xなどが該当します。GK104はGeForce GTX680などが該当します。GK110とGK104をまとめてKeplerアーキテクチャと呼びます。Keplerの前世代がFermiアーキテクチャで、GF100のGeForce GTX480からGF118のGeForce GT610までが該当します。GCNアーキテクチャははRadeon HD 7xxx世代(とおそらくRadeon HD 8xxx世代)が該当します。

■基本スペック

コア数が2880になり(GK104比で7/4倍)、メモリバスが384bit(GK104比で3/2倍)になりました。トランジスタ数は71億です。ベースクロックは836MHzです。

3SMXで1GPCなので、GPC数は5です。GK104は2SMXで1GPCだったので、トライアングルセットアップ能力はコア数ほど上がっていません(1クロックあたりのトライアングル数はGK104比で5/4倍)。テクスチャユニットは224個、ROPは48個です。

GK110は倍精度のスループットを1/8にするかしないかを変更できます。1/8にしなかった場合、コアクロックが下がります。

■命令スループット

CUDA C Programming Guide

1スレッドあたりの最高スループットの逆数を示します。1が最も好ましく、2や3ならば2倍・3倍遅い命令という意味です。Fは浮動小数点数、Iは整数演算です。

アーキテクチャ GK110 GK104 GCN
F32加算 1 1 1
F32乗算 1 1 1
F32積和 1 1 1
F32算術関数(*) 6 6 おそらく3か4
I32加算 8/7 8/7 1
I32乗算 6 6 4
I32積和 6 6 4
I32除算(**) 複数命令 複数命令 複数命令
I32シフト 3 6 -
I32比較 8/7 8/7 -
I32 SAD 6 6 4(***)
I24加算 おそらく8/7 おそらく8/7 1
I24乗算 複数命令 複数命令 1
I24積和 複数命令 複数命令 おそらく1
I24算術関数 - - -
論理演算 8/7 8/7 1
F64加算(#) 3 24 おそらく2
F64乗算(#) 3 24 4
F64積和(#) 3 24 4
F64算術関数(*)(#) - - マイクロコード
I64加算 - - 4
I8,I16->F32型変換 3/2 3/2 -
64型変換(#) 3/2 8 -
型変換(#) 6 6 -
ローカルメモリ同期 128 128 -
(*)GeForceの算術関数はCUDA Coreから独立したSFUで並列実行可能、スループットは逆数、逆平方根数、二進対数、2の指数、正弦関数、余弦関数のもの(**)GeForceは”below 20 instructions”との記述あり、おそらく100cycle前後(***)8bit整数は1、16bit整数は2と思われる。GCNのホワイトペーパーと命令エンコーディングより推測(#)GeForce GTX Titanのスループットは倍精度フルクロック時

なぜかCUDA 4.2のドキュメントと値がかなり食い違っているのですが…見なかったことにすればいいんでしょうかね。ここでは最新版の値を使いました。

GK110とGK104の違いは倍精度浮動小数だけでなく、こっそり「32bit整数シフト」が2倍高速化されています。CUDAなどでスレッドIDをシフトして使うことはよくあるので、これは助かります。といっても、GeForce GTX460に代表されるGF104やGF114の時代のスループットに戻っただけですが。

ところで、GK104ではWarp内スレッドデータ交換命令(__shfl()など)が追加されたので、この命令のスループットがすごく気になるのですが、誰か知りませんかね。スレッド同期が128cycleも待たされるらしい(上記ソースの表の下にある”Synchronization Instruction”参照)ので、この命令も遅かったらGPGPUが大変しにくくなるのですが。あとAtomic演算も不明です。

■L2キャッシュ

1.5MBに増えました。GK104は512kB、GF100/110は768kBでした。

■メモリアーキテクチャ

GK110ではTexture Cache(容量24kB?)とUniform Cahce(容量8kB?)がなくなりました。その代わり、容量48kBのRead-only Data Cahceが新設されました

参考:NVIDIAが世界最多トランジスタ数のチップ「GK110」を公開

Read-only Data CacheはTexture Cacheとして使うだけではなく、テクスチャ読み込み以外の場合でもRead-only Data Cahceを参照することができるようになりました(L1キャッシュには入りません)。CUDAにおいてconst __restric修飾子をつけた場合に使われるようです。HLSLのTexture2D.Load()時にもバイパスされるかどうかは不明です(もしできるならシャドウマップやバイキュービック補間に非常に有用なのですが)。

参考:GTC 2012 – 見えてきた次世代科学技術計算向けKepler(メモリ編)

■レジスタ数

総レジスタ数は変わりませんが、GPUネイティブの命令フォーマットが変わり、1スレッドあたりの最大レジスタ数が255に増えました。GK104は63、Fermiは128でした。ループをアンロールしまくってもL1キャッシュに退避されてしまう可能性が下がります。ただし総レジスタ数は変わっていないので、使いすぎるとOccupancyが下がります。

■新しいアトミック演算命令

64bit単位のatomicMax()、atomicMin()、atomicAnd()、atomicOr()、atomicXor()に対応しました。

■倍精度演算での2命令ディスパッチ

レジスタファイルの読み込みがなければ、倍精度演算命令を1Warpにつき同時に2命令ディスパッチできます。

■Dynamic Parallelizm

GPUが自らカーネル関数を起動できる機能です。マンデルブロ集合のように、高い解像度が必要な部分とそうでない部分が混在するとき、そうでない部分を実行しなくて済みます。個人的にはかなり革新的な技術だと思っています。(2/23追記:残念ながらTesla以外では使えないようです)(3/1追記:manaviのAndo Hisaさんの記事によると、GeForceでも使えるそうです。ただ、計算時間が無限に増えていくDynamic ParallelizmをWindows上で使うとTDRによりドライバごと殺されそうです)

■Hyper-Q

CUDA Work Distributorが32個に増え、CPUとGPU間で同時に32 MPIプロセスが並列実行できます。GK104以前は1個でしたが、カーネル関数の起動自体は同時に16までできました。(2/23追記:残念ながらTesla以外では使えないようです)(3/1追記:manaviのAndo Hisaさんの記事によると、GeForceでも使えるそうです)

■GPU Boost 2.0

GPU温度を基準としたブーストと、電圧変更に対応しました。

■Display Overclocking

垂直同期を取ったままディスプレイのフレームレート以上の速度でレンダリングできるようになります。

ここから、ベンチマークの結果を見ていきます。

「NVIDIA GeForce GTX Titan 徹底攻略」 – シングルGPUの最強候補を完全検証(mynavi)

Nvidia’s GeForce GTX Titan reviewed(techreport)

Benchmarking GeForce GTX Titan 6 GB: Fast, Quiet, Consistent(tom’s hardware)

「GeForce GTX TITAN」レビュー。999ドルの超巨大GPUは速いのか?(4gamer)

GK110がついに使える!──「GeForce GTX TITAN」の“破格”なパワーを知る(ITmedia)

GeForce GTX TITANはWQHD解像度で60fpsをキープ可能?(ASCII)

■ピクセルフィル、テクスチャフェッチ

テクスチャとROPのフィルレートを、3DMark VantageとBeyond3D suiteから見ます。整数とFP32のテクスチャフィルタ能力が大きく上がっています。

GPU Titan GTX680 HD 7970
理論ピクセルフィル[Gpixels/s] 42 34 34
理論テクスチャフィル(int8)[Gtexels/s] 196 135 134
理論テクスチャフィル(fp16)[Gtexles/s] 196 135 67
参考:メモリ帯域[GB/s] 288 192 288
Color fill [Gpixels/s] 16.3 12.9 13.8
int8 textire filtering [Gtexels/s] 143 108 124
fp16 texture filtering [Gtexels/s] 126 102 67
fp32 texture filtering [Gtexels/s] 54 35 33

■テセレーション

テセレーション性能を見ます。techreportのTessMarkを見ると、テセレーション性能が5割ほどの伸びています。テセレーションはSMX(厳密にはPolyMorph Engine 2.0)の数に応じて増えます。TeslaのようなGPGPUにしか使わない場合ただの無駄機能になってしまうのですが、そんなことは気にせず載せてきたNVIDIAはなかなかワイルドです。

GPU Titan GTX680 HD 7970
理論値[Gtris/s] 4.4 4.2 2.1
TessMark X16 49689 34055 36127
TessMark X32 29292 19387 15639
TessMark X64 12708 8503 4853

—-

■3DMark Vantage Feature Test

困ったことにtechreportとmynaviで全然違います。Parallax occlusion mappingがやたら遅かったり、SLIやCFで上がるはずのパフォーマンスが下がったりしていて、考察できるような状態ではないです。とりあえず、TitanはどのベンチマークでもGTX680から40%程度パフォーマンスが向上していることは分かります。

techreport版

GPU Titan GTX680 HD 7970
Parallax occlusion mapping 140 96 134
Cloth 92 62 65
Particle 143 101 102
Perlin noize 303 188 276

mynavi版

GPU Titan GTX680 HD 7970
Parallax occlusion mapping 16.9 13.8 13.4
Cloth 138.5 95.9 126.7
Particle 94.1 67.6 115.8
Perlin noize 148.3 110.4 98.2

■Sandra 2013 汎用処理

処理の中身はよく分からないけどGPGPU性能を見るベンチマーク。4gamer、mynavi、tom’s hardwareの3サイトでベンチマーク結果が公開されています。4gamerとtom’s hardwareはほとんど同じ結果ですが、manaviのほうは結果が悪いです。CPUなどの環境の違いで変わってくるので不思議ではないのですが、とりあえず両方の結果を載せます。

32bit小数ではTitanよりRadeon HD 7970の方が速く、64bit小数ではTitanの方が速いです。相変わらずOpenCLとDirectComputeでブレがありまくりです。GeForceについては、32bitではDirectCompute>CUDA>OpenCLで、64bitではCUDA=OpenCL>>>DirectComputeです。Radeonでは常にOpenCLの方が速いです。

それにしてもmynaviはDoubleの1/8クロック有効と無効で1割以下の差がないのが気になります。クロック差を考えたら2割弱の差がないとおかしいのですが。

tom’s hardware

GPU Titan Titan(Double) GTX680 HD 7970
FP32 OpenCL 4.000 3.330 2.420 5.150
FP64 OpenCL 0.330 1.870 0.213 1.530

mynavi

GPU Titan Titan(Double) GTX680 HD 7970
FP32 OpenCL 3.27 2.91 2.19 4.86
FP32 DirectCompute 4.85 4.48 3.22 3.31
FP32 CUDA 3.94 3.67 2.88 NA
FP64 OpenCL 0.31 1.71 0.19 1.23
FP64 DirectCompute 0.11 1.11 0.08 0.66
FP64 CUDA 0.34 1.84 0.21 NA

■Sandra 2013 暗号

AES256暗号化、AES256復号、SHA-256ハッシュ化の速度を見ます。整数演算だけなので、浮動小数点数の能力は関係ありません。tom’sは有効桁数が少なすぎるので、manaviのみ示します。太字は各処理・各GPUのなかで最も速かった値です。

相変わらずRadeonのOpenCLがやたら速いです。GK110の方が40%もコア数が多いのに、なんでこんなに違うのか不思議でしょうがありません。考えられるのは、整数シフトと型変換のスループットです。特にAESやSHAはシフト(と論理演算)を沢山使います。GCNがそれらを何クロックでできるのか不明ですが、もしかしたら1クロックでできるのかもしれません。

シフトといえば、GK110はGK104よりスループットが2倍速くなりました(命令スループット参照)。AES復号やSHAが2倍以上速いのは、単にコア数が増えたからだけではなく、シフト演算の高速化が影響したからだと思われます。

DirectComputeとOpenCLに差があるのも不思議です。DirectComputeは32bitの整数型しか用意されていないので、8bit単位のアクセスでは遅くなるはずです。なので、SHAの結果がどうも納得できません。

GPU Titan Titan(Double) GTX680 HD 7970
AES Enc OpenCL 12.30 10.40 7.28 28.80
AES Enc DirectCompute 10.47 9.27 4.81 17.78
AES Enc CUDA 11.15 10.00 8.19 NA
AES Dec OpenCL 16.23 15.47 7.18 28.88
AES Dec DirectCompute 13.32 8.88 4.71 18.19
AES Dec CUDA 10.96 10.25 8.38 NA
SHA OpenCL 9.84 8.47 4.72 28.24
SHA DirectCompute 16.92 13.13 6.11 13.46
SHA CUDA 11.57 10.46 5.69 NA

■Sandra 2013 Video Shader

マンデルブロ集合をHLSL/GLSLを使って描画するベンチマークらしいです(Dynamic  Parallelizmは非使用)。マンデルブロ集合の計算は、乗算や比較・分岐の比率が高くなります。

32bit浮動小数はHD 7970が、64bit浮動小数はTitanが若干速いです。64bitの方はTitanとHD7970のTFLOPS値(1.13 vs 1.00)の差を考えれば納得できます。しかし32bitのTFLOPS値は4.5 vs 4.0でTitanのほうが速くないとおかしいので、Titanの方が効率が悪いことになります。とはいえGTX680の3.09TFLOPSからはFLOPS値に見合うだけの性能アップをしていることから、Titanが悪いのではなくKepler自体の問題に思えます。しかし考えられる原因が多すぎてこれだけでは何とも言えません。

さっきとは打って変わって、Direct3DとOpenGLで差が全くありません。これが普通なのですが。

GPU Titan Titan(Double) GTX680 HD 7970
FP32 D3D11 1.60 1.37 1.00 1.63
FP32 OpenGL 1.58 1.36 1.00 1.63
FP64 D3D11 0.17 0.87 0.11 0.80
FP64 OpenGL 0.17 0.86 0.11 0.80

■PCI Express

GK110はPCI Express Gen3に対応します。しかし、Intelのチップセット(X79やZ77など)では強制的にGen2まで落とされます。実際mynaviではGen2で動作していることがベンチマークから読み取れますし、Legit Reviewsというサイトに記載されているGPU-ZのスクリーンショットではGen2と判定されています。一方、ITmediaやASCIIはGen 3と判定されており、よくわかりません。

■まとめ

GK110はGK104に比べ、倍精度浮動小数点数演算と整数シフトのスループットが改善されました。GPGPU能力はGK104から順当に向上していますが、処理によってはGCNより効率が悪いままのものもあります。


NVIDIA Tegra4 / Tegra4iのCPUとGPUのスペック

$
0
0

ISSCC 2013でNVIDIAからTegra4とTegra4iのスペックが詳細に語られたようなので、まとめました。

【重要】情報の信頼性は保証しません。

ソース:NVIDIAがMWCに合わせて「Tegra 4/4i」の詳細を明らかにNVIDIA、Tegra 4の詳細をついに公開 – CPUだけでなくGPUも大規模アーキテクチャ変更と明らかにNVIDIA Tegra 4 Architecture Deep Dive, Plus Tegra 4i, Icera i500 & Phoenix Hands OnNVIDIA Tegra 4 Family CPU Architecture(PDF注意)、NVIDIA Tegra 4 Family GU Architecture(PDF注意)、ARMのinfocenter

■SoCスペック比較

Tegra4と他社の最新SoCの比較です(怪しい部分が多々あります)。

SoC Tegra4 Snapdragon800 Exynos5450 AppleA6X Z2760
メーカー NVIDIA Qualcomm Samsung Apple Intel
ISA ARMv7 ARMv7 ARMv7 ARMv7s x86
FPU ISA VFPv4 VFPv4 VFPv4 VFPv4 SSSE3
製造 TSMC 28nm HPL TSMC 28nm HPM Samsung 28nm Samsung 32nm Intel 32mn P1269
メインCPU Cortex-A15 Krait 400 Cortex-A15 Swift Cloverview
コア数 4 4 4 2 2
スレッド 4 4 4 2 4
クロック 1.9GHz 2.3GHz 0.2 – 1.8GHz 1.4GHz? up to 1.8GHz
L0キャッシュ(I/D) NA 4kB(1way) + 4kB(1way) NA - NA
L1キャッシュ(I/D) 32kB(2way) + 32kB(2way) 16kB(4way) + 16kB(4way) 32kB(2way) + 32kB(2way) 32kB + 32kB 32kB(8way?) + 24kB(6way)
L2キャッシュ shared 2MB(16way) shared 2MB(8way?) shared 2MB(16way) shared 1MB shared 1MB(8way)
パイプライン 15-24 11- 15-24 - 16-
OoO Yes Yes Yes - No
デコード 3命令 3命令 3命令 3? 2命令
発行 8命令 7命令? 8命令 5? 2命令
実行ポート 8 7 8 5? 4
省電力CPU Cortex-A15 NA Cortex-A7 - NA
コア数 1 NA 4 - NA
クロック ? NA 0.2 – 1.2GHz - NA
L2キャッシュ 0.5 MB NA 0.5MB - NA
GPU ULP GeForce Adreno 330 PowerVR SGX544MP3 PowerVR SGX554MP4 PowerVR SGX545
vec ALU 24+48 256? 48 128 16?
クロック 672MHz - - 280MHz? 533MHz
GFLOPS 96.8 100? - 71.7? 19.2
Direct3D 9 level 1? 9 level 3 9 level 3 NA 9 level 3
OpenGL ES 3.0? 3.0 2.0? 2.0 2.0
OpenCL NA 1.1? 1.1 1.1 NA
メモリ LPDDR3
LPDDR2
DDR3L
LPDDR3 LPDDR3
LPDDR2
DDR3L
LPDDR2? LPDDR2
クロック 1866MHz 1600MHz 1600MHz - 800MHz
バス 64bit 64bit 64bit 128bit 64bit
帯域 14.9GB/s 12.8GB/s 12.8GB/s - 6.4GB/s
容量 up to 4GB - 2GB 1GB 2GB

この記事を書いているときにタイミング悪くAtom Z2580が出てしまいましたが、面倒なので改定していません。CPUが2.0GHz、GPUがPowerVR SGX544MP2、メモリはLPDDR2のままです。

Tegra3はCortex-A9(2.3GHz)、Tegra4はCortex-A15(1.9GHz)をベースにしています。

Cortex-A9は最大4コア、2命令フェッチ・デコード、4命令発行のアウトオブオーダ実行です。ライトバックは7命令です。整数ALUのパイプラインはライトバックを含めて9~11段です。実行ポートは4つあり、ALU1(Alithmetic Logic Unit)、ALU2、乗算器、VFP・NEON・AGU(Address Generation Unit)です(NEONへの2命令発行は不可能)。NEONパイプのみ分離しています。命令プリフェッチステージには、命令キャッシュ、Fast Loop Mode、プリフェッチユニットの3ブロックがあります。Fast Loop Modeは64バイト以内の小さなループを検出してキャッシュします(Intel Core2のLoop Stream Detectorに相当)プリフェッチユニットには、4096エントリ(各2bit)のGHB(Global History Buffer)、512エントリの2way BTAC(Branch Target Address Cache)、8エントリのReturn Stackがあります。ROBは32~40命令で、(おそらく)OoO Writeback Stageにあります。RSは全実行ポート共有で、命令数は不明です(8命令?)。物理レジスタは56本で、フラグレジスタ用に9bitの物理レジスタが8本あります。レジスタリネーミングは1サイクルで最大2本です。ALUは1~3サイクルかかります(例:レジスタ指定シフトつき加算は3サイクル)。FPUはVFPv3で、オプションです。大抵の命令はスループット1で処理できます(意外にも32bit/64bitどちらもスループット1、レイテンシは4以上)。NEONはシンプルな命令のみ128bit幅のALUで、オプションです(が、Tegra2以外でNEONがないSoCを見たことがない)。TLBは2レベルです。L1 TLBはuTLBと呼ばれ、データ32エントリ、命令32エントリで、1wayです。L2 TLBは一般に128エントリで、2wayです。プリフェッチャーは8ストリームです(r3以降は16ストリーム?)。ストアバッファが4エントリ(1エントリにつき64byteのデータ+32bitのアドレス)あります。L1キャッシュは32byte(8ワード)キャッシュラインで4wayで、16 or 32 or 64kBです(一般に32kB)。ただし、フェッチは1サイクルにつき64byteまでです。L2キャッシュはコアとAXIバスの間にあり、コア間共有で、32byteキャッシュライン、128kB~8MB(一般に1コアあたり256 or 512kB)、4~16wayです(512kB/1coreのとき8wayにすることが多い)。レイテンシを下げるためにL2キャッシュを半クロック動作にすることができます。また、L2を排他キャッシュにするかどうかを変更できます。TSMC 40nm Gプロセスで最大2.0GHzで動作します。

余談ですが、Cortex-A9はメモリアクセスのアウトオブオーダができない、FPUパイプではアウトオブオーダと投機実行もできないという噂がありますが、本当かどうかは未検証です。

Cortex-A15は最大16コア(1モジュールあたり最大4コア)、3命令フェッチ・デコード、8命令発行のアウトオブオーダ実行です。整数ALUのパイプラインはライトバックを含めて15段、NEONは16~24段です。実行ポートは8つあり、2つのSimple Cluster、1つの分岐、2つのComplex Cluster、1つのMultiply Divide Cluster、2つのLoad&Storeです。ループ検出はLoop Bufferに名前を変え、デコードステージに併設され、32エントリのuOpをキャッシュします(Core iのLoop Stream Detectorに相当)。Global History Bufferは2レベル構成で容量不明です。BTACはBTB(Branch Target Buffer)に名前を変え(Cortex-A8時代の名前に戻った)、2つの前方ジャンプと1つの後方ジャンプを予測できます。BTBは2レベル構成になり、L1 BTB(microBTB)は1way 64エントリです。L2 BTBのエントリ数は不明ですが、間接分岐のためのBTBが256エントリあります。Return Stackは不明です(8~32エントリ?)。ROBは128 uOp(60 uOp説もあり)、RSは40 uOp以上です。物理レジスタは不明で、ARMレジスタ用とNEONレジスタ用の2種類があります。Simple Cluster(VFPレジスタを使った整数SIMD命令を含む)やBranchは1サイクル、Load&StoreやMultiply Divide Clusterは4サイクル(LoadとStoreは限定的アウトオブオーダでそれぞれ1クロック1命令まで)、Complex Cluster(NEON命令やVFP命令)は2~10サイクルです。Cortex-A15では整数除算命令とSIMD積和命令を新たにサポートします。FPUはVFPv4で必須です。NEONのbit幅は不明です(64bit?)。Complex Clusterには。各ポートに8エントリのキューがあります。Load&Storeには16エントリのキューがあり、ARMレジスタとNEONレジスタで共用です。L1 TLBはデータ読み込み32エントリ、データ書き込み32エントリ、命令32エントリで、1wayです。L2 TLBは512エントリで、4wayです。L1キャッシュは64byteキャッシュラインで2wayで32kBです(フェッチは1サイクル128byteで、アライメント不要)。L2キャッシュは64byteキャッシュラインで16wayで0.5 or 1 or 2 or 4MBです。TSMC 28nm HPで最大2.5GHzで動作します。

表を作るのが面倒なので文章で書いてしまいましたが、Cortex-A15のCortex-A9に対する利点は、3命令並列実行(とそのためのパイプライン・キャッシュの強化)、NEONパイプラインが2倍、アウトオブオーダの強化、TLBの増量、VFPv4などです。

Tegra4はソフトマクロで提供されたCortex-A15をあまり弄ることなく実装していると思われます。Qualcommにかなりライバル心を燃やしているようで、KraitがL2キャッシュが共有でない(コア単位独立で各512kB、これはKraitが非同期SMPのためらしい)こと、ROBが40エントリしかないこと(Tegra4は128uOp)、L1データキャッシュが16kBしかないこと、電力抑制コアがないなど、細部に渡ってKraitの劣る点を指摘しています(”OoO window lookup size”がROPを指すのかRSを指すのか不明ですが、RSが128というのは有りえないと思うのでROPとしています。ちなみにIntel Core2は3RS,96ROBでCortex-A15の方が上だったりします)。

余談ですが、KraitはARMのCortex-A15が出る前に独自にCortex-A15相当の機能を実装したもので、Kraitの前身であるScorpionでもCortex-A9が出る前にCortex-A9相当の機能を実装しています。ARMより機能を先取りして製品化できる点は良いのですが、ScorpionはCortex-A9よりわずかに性能が低くなりがちで、KraitもCortex-A15より若干性能が低くなる可能性があります。

Tegra4iはCortex-A9 r4です。r4は製品リビジョンを表しています(おそらくcat /proc/cpuinfoしたときに表示されるrevisionに相当するものと思われます)。Tegra3はr2でした。ARMによるとr0p0、r1p0、r2p0、r2p1、r2p2、r3p0、r4p0、r4p1があり、r4p0に相当するものと思われます。リビジョン間の違いは、エラッタ(バグ)の修正や、電力管理やキャッシュなどの制御用レジスタの追加などがあるようですが、機能的な違いはほとんどありません。r0のCortex-A9はTSMC 40nm LP or Gプロセスをターゲットにしています。おそらくr4では28nmにターゲットを移し、高クロックで動作できるようにするなどの若干の改良を加えたものと思われます。Tegra4ではL2 BTBが128エントリから512エントリに増やされていますが(Cortex-A15と同等)、これがNVIDIA独自の改良なのかARMのリビジョン変更による改良なのかは不明です。ホワイトペーパーを見るとNVIDIAが設計したものをARMが採用したように読めなくもないです。また、分岐の”History Buffer”と分岐予測アルゴリズムもCortex-A15相当に引き上げられ、L1データキャッシュのプリフェッチが新設されました(History BufferがBTBなのかGHBなのかは不明)。

ちなみにTegra4iの製造プロセスはTSMC 28nm HPM(HPLではありません)で、Snapdragon 800と同じです。メモリはシングルチャネル32bit接続で、DDR3L-2166をサポートします。DDR3L-2166というと、今デスクトップPCで標準のDDR3-1600より3割以上速いメモリになります。そんな無理をするより(他のメーカーがそうしているように)メモリをデュアルチャネル接続にすればいいと思うのですが、どうもNVIDIAはデュアルチャネルが嫌いのようです。

■OpenGL ES 3.0を見据えた新機能サポート

GPUクロックが672MHzという、GeForce GTX480に追いつきそうな高クロックも驚きですが、GPU内部のアーキテクチャはさらに興味深いものでした。

OpenGL ESの対応バージョンは非公開のままですが、3.0に必須の機能がほぼ全て備わっています。4x MSAA(Tegra3は5x CSAAのみ対応)、24bit深度バッファ(Tegra3は16bit)、深度テクスチャ、テクスチャ配列、環境マップ、テクスチャフィルタ時の境界色、PCFフィルタ、4k解像度テクスチャ、FP16テクスチャとブレンド、sRGBテクスチャとブレンド、ジオメトリインスタンシング(Direct3D 9レベル)、オクルージョンクエリ、非正方行列、マルチレンダーターゲット、サーフェイスなしのコンテクスト生成、Uniform Buffer Object、PBO、Separate Shader Objects、Explicit Attribute Location、Framebuffer Blit、ARB_copy_buffer、RG8テクスチャなどを新たにサポートします。

一方で、EACやETC2などの新しい圧縮テクスチャに対応しません(ETCとDXTCで代用)。CSAAも対応しません。

プログラマブルブレンドなど、Tegra3の独自Extensionも引き続きサポートするようです。

■グラフィックス効率とダイ面積を重視してGPGPUの正反対に突っ走ったULP GeForce

(2/27追記)一部勘違いがあったため修正しました。今後しばらく記述が二転三転するかもしれません。

Tegra4でもユニファイドシェーダに移行しないことを以前から公開していましたが、その理由はコアあたりのダイ面積削減にあったことが分かりました。PowerVR、Adreno、Mali、Vivanteなど他のメーカーがユニファイドシェーダを採用してリッチな演算ができる方向に向かっているのとは正反対に、Tegra4のGPUは機能を抑えてコアを小さく抑えることに注力しています。

頂点シェーダは4コア(4ALU)を1つのVPE(Vertex Processing Engines)にまとめました。VPEが6個なので、24コアになります。VPEは32bit浮動小数点数(GLSL ES 3.0におけるhighp精度に相当)の4way SIMD積和命令を1クロックにつき1つ実行できます。Tegra3やPowerVRでは精度を落とす代わりにSIMDのデータ数を増やすことができるので、Tegra4でも16bit浮動小数点数(mediump精度)なら8way SIMDとして実行できるのではないかと思われます。1サイクルあたりのトライアングルセットアップ数はTegra3と同じです。

Tegra4iでは、VPEが3個になり、結果として全部で12コアになります。

ROPは4です(深度ステンシルは最大8?)。Tegra3のROPは2でした。Tegra4iも2 ROPです。Tegra3から早期Zカリングのアルゴリズムを見直し(1クロックあたり最大8ピクセルの判定・破棄が可能)、深度バッファの精度が内部20bitから24bitに上がりました。

VPEには16kBの頂点キャッシュがあります。頂点キャッシュはVBO(Vertex Buffer Object)を96エントリまで格納します(Tegra2やTegra3は32エントリ?)。1エントリはおそらく1頂点に対応すると思われます。ここで、エントリ数を無駄なく使い切るには1頂点あたり何バイトまでに抑えなければならないかを計算します。16384÷96=170.677…で、170バイトまで使えます。座標のために3変数、法線のために3変数、テクスチャのために2変数、頂点色のために4変数を使うとき、48バイトです。あれ?多すぎますね。もしかしたら3頂点~4頂点で1エントリなのでしょうか。これは分かり次第検証したいと思います。

ピクセルシェーダは4コアのグループを3つまとめてPFS(Pixel Fragment Shader)としています(PFSは私の造語です。毎回Pixel Fragment Shaderと書くと大変なので)。PFSが4個なので、4×3×4=48コアになります。4コアごとに1つのMFU(Multi Function Unit)が付随します。MFUはTegra4から新設で、算術関数、逆数、平方根、mov命令などを実行します。PFSには1つのROP(メモリバスではなくピクセルシェーダ内にROPがあります)、4kB L1ピクセルキャッシュ、L1テクスチャキャッシュ、テクスチャフィルタがあります。GeForceでいうSMXのようなイメージです。PFSの外に共有16kB L2テクスチャキャッシュがあります。1クロックあたりのピクセルフィル・テクスチャフィルはTegra3の2倍です。16x異方性フィルタができる点はTegra3と同じです。

Tegra4iでは4コアのグループを6つまとめて(Tegra4の倍)PFSとしています。総コア数は同じですが、PFSの数が半分に減るので、テクスチャフィルレートは半分に落ちます。

ピクセルシェーダ内のコアは最高20bit浮動小数点数です。これはOpenGL ES 2.0/3.0でいうmediump精度に相当します。よって、highpが非サポートであることを意味します。Tegra2、Tegra3の内部精度も20bitなので、NVIDIAは精度を軽視したことになります。

もう少し詳しく説明します。OpenGL ES 2.0の仕様では10bit精度でmediump、16bit精度でhighpを要求します。仮数部と指数部と符号部を合計して20bitのTegra3(13bit+6bit+1bit?)は、highpに対応していません(それでいいのかという話はすぐ後で)。OpenGL ES 3.0はmediumpの精度は変わっていないので、Tegra3の精度で計算しても仕様違反ではありません(ただし整数は10bitから15bitに増え、符号なし整数のサポートも必須)。一方、highpは24bit精度(IEEE754 single precision相当)を要求するので、highpは非対応ということになります。じゃあTegra4はOpenGL ES 3.0に対応しないのかというと、そうではなくて、実はピクセルシェーダに限りhighpはオプションです(OpenGL 3.1以降がhighp必須だった…記憶が正しければ)。なので、mediumpまでの対応でOpenGL ES 3.0対応を名乗ることができます。Tegra4がOpenGL ES 3.0の仕様を無視したと主張する記事が多いので、念のため。ただし、Tegra以外で24bit精度をサポートしないGPUはARM Mali-400くらいしか現存しません(ARM Mali-T604以降はユニファイドシェーダなので24bit精度のはず)。速度犠牲でもhighpで動くモードがあればよいのですが。

PowerVR、Adreno、MaliはGPGPU対応を謳っており、実際OpenCLのSDKを公開しています。GPGPUには32bit精度が必要で、Tegra4はGPGPUをばっさり切って捨てたことになります(32bit精度のVPEで無理やりGPGPUすることも出来なくはないですが)。ただし、画像処理は基本的に8bit整数精度で間に合うので、”Computational Photograph Architecture「Chimera」API”によってGPUを活用したRAW現像やコンピュータビジョンを実現する計画のようです。GeForce 6/7時代の古典的GPGPUといえそうです。が、CPUが4コアもある(しかもCortex-A15だからNEON用のSIMDパイプラインが2つもある)のだから、そっちでやればよい気もするのですが。正直、モバイルでOpenCLが活躍したところを見たことがありません。ホワイトペーパーによると、Bayer配列の変換、YUV変換、HDRのトーンマッピングなどのためにGPUを使うようです。

1ピクセルあたりのレジスタ数が16から24に増えました。インフライトに扱えるスレッド数は不明です。

命令セットはVLIWです。nコア+(4-n)コア+MFUの最大3way VLIW(あるいはテクスチャサンプル命令を含めて4way VLIW?)だと思われます。4つに纏められたコアに1つの”しきい”を入れることで1+3、2+2、3+1、4+0のように分け、それぞれ別の命令が実行できます。これはGeForce6のピクセルシェーダの(変態)アーキテクチャそのものです。そういう意味では、MFUはGeForce6のmini-ALU(Scalar ALU)に相当するかもしれません。

VLIWなのでコンパイル時に命令レベルの並列化を行うことになります。RadeonもHD 2xxxからHD 6xxxまでVLIWでしたが、こちらはVLIW命令長が必ずALUの数と一致していたのに対し、ULP GeForceではALU数よりVLIW長の方が短いです。よって、できるだけ変数を(GLSLの)vec4型にまとめて一気に演算した方が、効率のよいVLIW命令を生成できるでしょう。スカラ演算だけの場合はVLIWに命令を2個しか詰め込められないので、半分のALUが遊ぶことになります。一方で、アルゴリズム上どう頑張っても命令を並列化できないときに、VLIWに空き命令が出現してしまう可能性は低くなります。GeForce6ベースのVLIWは、ダイ面積(言い換えれば電力効率)とVLIW充填率(ALU実行効率)のバランスをとったアーキテクチャであり、落としどころとしては悪くないと思います。GPGPUは犠牲になりました。

■ダイ面積最重視

ソースに示したサイトではSnapdragon、Exynos、AppleAxのGPU面積の比較がありますが、Tegra4のGPUは他の半分以下しかありません。ピクセルシェーダが20bitとはいえ、この面積でこれだけのALUを敷き詰めるのはなかなか困難だと思います。その代わり、高クロック動作と熱密度向上という問題が生まれるわけですが、まぁ、問題ないと判断したのでしょう。

■OpenGL ES 3.0に対応するのかしないのか良く分からないTegra4

結局、ホワイトペーパーにはっきりと「OpenGL ES 3.0対応」と書かれることはありませんでした。触れられているのは「EAC/ETC2や32bit浮動小数などのOpenGL ES 3.0の機能を完全に(explicitly)サポートしない」「多くの重要なOpenGL ES 3.0の機能をサポートする(図付き)」「OpenGL ES 3.0の使用はしばらく(for quite some times)期待しない」だけです。こう書かれるとOpenGL ES 3.0に対応しないようにも取れます。

ちなみに、Androidは5.0からOpenGL ES 3.0に対応するようです。

■感想

ハードがすごいのは分かったけどマーケティングとかファブの問題でコケたりしないか不安


PerfHUD ESを使ったTegra搭載機でのOpenGL ESデバッグ

$
0
0

NVIDIAのPerfHUD ESを使い、Tegra3を搭載したAndroidタブレット(Google Nexus 7)でOpenGL ES 2.0のデバッグを試しました。

PerfHUDはNVIDIAが無償提供する3Dアプリケーションのパフォーマンスアナライザです。PerfHUD ESはそのAndroid版で、OpenGL ES 2.0に対応しています(OpenGL 1.xは非対応)。現在のバージョンは1.96で(公式サイトでは1.98と書かれていますが、なぜか1.96しかありませんでした)、Tegra2からTegra4までをサポートします。

ここでは、ホスト側PCがWindowsであることを想定して説明します。

■必須環境

Tegra2以降を搭載し、GPUデバッグが可能なAndroidスマートフォン・タブレット(Android 4.0以降ならほぼ対応)※root権限は不要
USB接続で通信できる(=Android SDKのadbがAndroidを認識できる)Windows/Mac OSX/Linux PC
OpenGL 1.5以降に対応したGPU(Windows Vista以降のPCならほぼ対応)

【注意】GeForce 6以降のNVIDIA製GPUが推奨だそうです(筆者環境はオンボロなIntel GM45)。

■ダウンロード

PerfHUD ESのサイトの”WHERE CAN I FIND IT?”内にリンクがありますが、実はTegra Registered Developer Programの参加登録をしなければForbiddenになりダウンロードできません。

Tegra Registered Developer Programに登録するには、NVIDIA Developer Zoneのアカウントを作成し、アカウントページのRegistered Developer ProgramsのTegra Registered Developer Programの右側にあるApplyを押し、必要な情報を入力します。その後審査(?)があり、許可が下りるとダウンロードできるようになります。このとき使用用途を英語で書く必要がありますが、筆者の場合30字くらいのありがちな(しかも英語として正しいのかどうかも怪しい)内容でも通りました。許可が下りるまで15分程度でしたが、人によっては半日かかることもあるようです。

許可が下りてログイン状態でリンクをクリックすると、Tegra Android Developer Pack(以下TADPと略す)がダウンロードされます。これはAndroid開発で使うツールを一式まとめたもので(Java SDKからOpenCVまで入っている)、この中にPerfHUD ESが入っています。ちなみに、筆者の場合、Cygwinにチェックが入っている状態でインストールするとエラーになりました(日本語環境では駄目なようです)。

■デバッグ開始までの手順

Adreno Profilerを使ったことのある人にとっては分かりやすいかもしれませんが、お世辞にも簡単とは言えません。

まず、Android端末のPerfHUD ESデバッグを有効化します。”C:\NVPACK\perfhud_switch\enable_perfhud.bat”を実行します。中身は、ただadb shellコマンドを実行しているだけです。デバッグが有効になるのはAndroid端末を再起動した後で、しかもまた再起動するとデバッグが無効になります。

次に、Android端末とPCの接続設定をします。まず、コマンド”adb forward tcp:7876 tcp:7876″を実行し、ポートフォアワーディングができるようにします。7876は、PerfHUD ESがデフォルトで使用するポート番号です。また、ファイアウォールのTCPポート7876番を例外設定します。Windowsファイアウォールの場合、詳細設定を開いて「送信の規則」と「受信の規則」の両方で「新しい規則」を作成し、TCPポート7876番を「許可」します。筆者環境では試していませんが、もしTADPに同梱されているADBのインストール時にアプリケーション単位で接続ブロックする設定にしてしまった場合、それも解除する必要があるはずです。ここまでの操作は、1度行えば接続解除後も引き継がれます。

そして、PerfHUD ESを実行します。デフォルトでは”C:\NVPACK\perfhud_es\PerfHUDES.exe”にあります。画面右下のアイコン(AndroidデバイスがPCに接続されていれば”Not connected.”と表示される)をクリックします。この操作を行うと、もし既にAndroid端末との接続状態であれば直ちに切断されます。Android端末でOpenGL ESアプリケーションが動作していれば、プロファイル可能なアプリが表示され、すぐにプロファイリングを始めることができます。そうでない場合、”ADB Launcher”にチェックを入れるとアプリが列挙され、デバッグしたいアプリを選択してダブルクリックする(あるいは”Connect”を押す)とプロファイリングが始まります。

【注意】デバッグするアプリケーションはINTERNETパーミッションを許可していなければならないようです。そうでない場合、”ADB Scan…”から進みません。ドキュメントのどこにも書かれていないような…

【注意】一部のOpenGL Extension APIを使用していると、プロファフィル開始直後にPerfHUD ESが無言で終了します。筆者環境では、GL_EXT_occlusion_query_boolean拡張のglBeginQueryEXT()を使っていると終了しました。

■PerfHUD ESでできること

PerfHUD ESには”Performance Dashboard”と”Frame Debugger”の2画面があります。

Performance Dashboardでは、リアルタイムにCPU使用率やフレームレート、API種別ごとの使用時間などが表示されます。テクスチャの解像度を強制的に2×2にしたり、フラグメントシェーダを無効にしたりすることで、ボトルネックがどこにあるのかを探すことができます。

perfhudes_pd

Frame Debuggerでは、APIの呼び出し回数、レンダーターゲット・深度バッファの可視化、APIトレース、ジオメトリビューア、状態ビューア、テクスチャビューア、シェーダビューア(リアルタイム編集も可能)ができます。画面下部にシークバーがあり、途中のDraw Callの結果も見ることができます。ただし、API呼び出しの回数が多いほど解析の時間も長くなります。

perfhudes_fd

【注意】Geometry Viewerは、モデルがインテックス付き(つまりglDrawElements()による描画)でなければ表示されないようです。Vertex Buffer ObjectとElement Array BufferとglBindAttribLocation()を組み合わせた状態では表示されましたが、Element Array BufferなしでトライアングルリストをglDrawArrays()した場合はエラーが表示されました。これもドキュメントのどこにも書かれていないような…(一応、別のドキュメントで「パフォーマンス向上のため、Tegra3は必ずインデックスバッファを使うことを推奨する」とは書かれてはいます)

【注意2】編集したシェーダを適用すると、glGetError()が1度だけエラーを返します。Snapdragon + Adreno Profilerでも同じことが起きるので、回避できないと思われます。プログラムがエラーチェックを行って強制終了するような仕組みがある場合、一旦無効にしなければなりません。

■終了

それなりの確率でPerfHUD ESがクラッシュするので、切断した後に終了することをお勧めします。尤も、実害はないのですが。

■使った感想

動作がやや重く、たまに不安定になるものの、必要な機能は一通り揃っており、GPUメーカーらしい作り込みを感じます。TegraでOpenGL ES開発をする人にはお勧めです。


OpenGL ESでETC1圧縮テクスチャを使う

$
0
0

PKMフォーマットに格納したETC1圧縮テクスチャを、AndroidからC言語でOpenGL ES 2.0に読み込ませてみました。

ETC1圧縮テクスチャは、OpenGL ESではオプション(GL_OES_compressed_ETC1_RGB8_texture)ですが、Android搭載のほぼ全てのモバイルGPUでサポートしています。ETC1テクスチャを格納するためによく使われるフォーマットとして、PKMとKTXがあります。KTXはDDSフォーマットのOpenGL版のようなもので、高機能ですが複雑です。今回は、シンプルなPKMフォーマットを使い、OpenGLへテクスチャをロードさせました。

■ETC1圧縮テクスチャとは

そもそも圧縮テクスチャ(Compressed Texture)は、GPUにおけるグラフィックスメモリの容量と帯域の削減を目的として使われています(どちらもモバイルSoCでは非常にボトルネックになりやすいポイントです)。圧縮テクスチャは一般に不可逆圧縮で、ハフマン符号化やランレングス符号化のようにビット長が可変長のフォーマットは採用されません。テクスチャのごく一部を読み込むだけでいいシーンで、わざわざ先頭からデコードしないといけないようなアルゴリズムでは困ります。そこで、多くの圧縮テクスチャは、テクスチャを小さなブロックに分割し、各ブロックに対して個別に圧縮します。Direct3DでサポートされているDXT1圧縮テクスチャ(OpenGLではGL_EXT_texture_compression_dxt1などで提供)では、4×4のブロックを単位とし、2つの16bit基準色と、4×4個の2bit補間値を持たせる構造になっています。つまり、1ブロックあたり2×16+4×4×2=64bitで、RGB16bitの非圧縮テクスチャに比べてたったの8分の1の容量で済みます。しかも、アルゴリズムが単純でハードウェアへの実装も簡単です。

しかし、DXT系のアルゴリズムはS3 Graphicsが特許を持っており、OpenGLとは(思想的な意味で)相性が良くありません。また、アルゴリズムが単純ゆえに品質が低く、ブロックノイズが見えたり、エッジにノイズが大量に乗ったりします。

ETC1はスウェーデンのエリクソン(正式にはテレフォナクティーボラーゲLMエリクソンらしい)が開発した特許フリーの圧縮テクスチャです。現在、Android搭載のSoCでETC1に対応しないものはありません(私が知る限りでは)。ARM Mali-400のように、ETC1以外の圧縮テクスチャをサポートしないGPUもあります。ETC1は、RGB24bitの非圧縮テクスチャを6分の1に圧縮します。アルファ値は格納できません。

ちなみに、iOSではPVRTC、Windows RTではBCxテクスチャのみが使え、ETC1は使えないようです。また、OpenGL ES 3.0やOpenGL 4.3からETC1の進化版にあたるETC2をサポートします。

■PKMフォーマット

ETC1/ETC2(以下、併せてETCnと略す)のためだけに作られたフォーマットで、非常にシンプルです。ETC1の旧名称がiPACKMANで、縮めてPKMになったのだと思われます。Android(2.2以降)ではandroid.opengl.ETC1クラスで読み書きすることができます。


struct etc1 {
  char magicNumber[4];
  char version[2];
  u16 type;
  u16 width;
  u16 height;
  u16 activeWidth;
  u16 activeHeight;
  char *data;
};

magicNumerは”PKM “(0x504B4D20)です。versionは”10″(0×3130)か”20″(0×3230)です。typeは普通0でETC1 RGBを表します。widthとheightは展開後の幅と高さです。activeWidthとactiveHeightはオリジナルの幅と高さです。ETC1は4×4ピクセルを1ブロックとして圧縮するので、activeWidthとactiveHeightを4を単位として切り上げるとwidthとheightになります。ここまでの16バイトがヘッダで、dataに実際の圧縮テクスチャが入ります。

圧縮テクスチャのデータのバイト数は、width×height×0.5で求められます。

バイトオーダはビッグエンディアンです。しかし、AndroidのARM版とx86版はリトルエンディアンなので、エンディアンの変換が必要です。しかもMIPS版はビッグエンディアンだそうで、プログラム側で条件分けしないと移植で問題が起きます。C言語なら”machine/_types.h”にある_BYTE_ORDERマクロで条件分けできますし、JavaならByteBufferのorderをBIG_ENDIANにすれば勝手に変換されます。が、個人的には独自に管理用XMLファイルなどを用意する方が楽な気がします。

KPMはミップマップをサポートしません。厳密にはバージョン”10″のみ対応しているそうですが、ツール側が対応していないことが多く、OpenGLのAPI呼び出しも複数回行わないといけないので、1ミップマップで1ファイルが一般的のようです。

■ETC1圧縮のためのツール

Mali GPU Texture Compression Toolがおすすめです。Windows版では、JPEGなどの画像ファイルを左側にドラッグ&ドロップし、File -> Compress selected images…を押すとオプション画面が現れ(このときOutput file formatをPKMにする)、OKを押すとデフォルトでユーザのホームフォルダ(C:/Users/[アカウント名]/)に*.pkmファイルができあがります。Compression speedをSlowにすると高品質になりますが、圧縮時間がかなり長くなります。また、Enable mipmapsを選択すると、1×1サイズになるまでの全レベルのミップマップが生成されます。

■OpenGL ESによるETC1圧縮テクスチャの読み込み

通常のテクスチャはglTexImage2D()を使いますが、圧縮テクスチャではglCompressedTexImage2D()を使います。PKMファイルを直接読み込ませる場合、fseek()などでヘッダを読み飛ばしてください。


glCompressedTexImage2D( GL_TEXTURE_2D, level, GL_ETC1_RGB8_OES, width, height, 0, numBytes, memAddr );

なお、OpenGL ES 2.0でミップマップを使用するときは、テクスチャサイズは2の冪乗でなければなりません。ただし、GL_NV_texture_npot_2D_mipmapなどのextensionがあれば制限が緩和されます。

JavaならばデータのInputStreamをandroid.openglETC1Util#createTextureに渡し、返されたETC1Util.ETC1TextureのgetData()メソッドをGLES20.glCompressedTexImage2Dの最後の引数に渡せばよいと思いますが、試していません。

■まとめ

AndroidならETC1はほとんど対応している

PKMファイルはビッグエンディアンでヘッダが16バイトある

glCompressedTexImage2D()とGL_ETC1_RGB8_OESを使う

■参考文献

Android OpenGL ES 2.0 の圧縮テクスチャ

opegl:texturefileformat

ETC1

ETC1Util.java

おしり


各種並列処理ライブラリの実験

$
0
0

OpenMP、並列パターンライブラリ(PPL: Microsoft Parallel Patterns Library)、C++AMP(C++ Accelerated Massive Parallelism)をちょびっと試しました。

Microsoft Visual C++シリーズでの開発を前提とします。

0. その前に

C++11のラムダ式の知識が必須(このへんとかを参照)

1. 動作条件

OpenMP : Visual Studio 2005以降(Express版ではWindows SDKが要るかもしれない)

PPL : Visual Studio 2010以降

C++ AMP : Visual Studio 2012

2. 各ライブラリの違い

OpenMP : クロスプラットフォームで対応するコンパイラが多い。pragmaディレクティブで簡単に並列化。

PPL : Microsoft独自。「同時実行ランタイム」の中で提供。ラムダ式と相性が良い。結構多機能。

C++ AMP : Microsoftと(たぶん)AMDが開発、規格はオープン。GPGPU(Direct3D 11のCompute Shaderに変換される)。PPLと統合したっぽい。

3. サンプル

奇偶転置ソートを試しました。符号付き32bit整数を昇順に並べ替えます。ソートのアルゴリズムとしては悪い(最悪計算量がO(N^2))ですが、アルゴリズムがシンプルなので使いました。本気で並列処理でソートするならばbitonic sortやradix sortが良いでしょう。

長いのでソースコードはpasetbinに置いておきます

oddEvenSort()が基本形です。oddEvenSort2()はループ変数が0から順になるように変形しています。

oddEvenSortOpenMP()がOpeMP版です。for文に#pragma omp parallel forをつけるだけです。コンパイラの設定でOpenMPを有効にしないと、無視されてシングルスレッドになるので注意してください。

oddEvenSortAmp()がC++ AMP版です。GPUのスレッドは0番から順にIDが振られるので、oddEvenSort2()がベースです。concurrency名前空間のarray_viewクラスが、CPUとGPUのメモリ空間の接続する窓の役割をします(Direct3D 11のUnordered Access Viewに相当)。extentがスレッド数です(OpenCLのget_global_id()に相当)。parallel_for_each()で処理を開始します。restrict( amp )をつけると、そのコードがGPU上で動作させることを知らせます。

oddEvenSortPPL()がPPL版です。.NET Framework 4.0のParallel Extensionsにソックリです。

4. 実行時間

N = 50000のときの時間を計測しました。単位は秒(小さいほど良い)。Visual Studio 2012 Professional。

Celeron(Penryn-L, 2core) + GMA4500MHD

Sort1 6.396
Sort2 6.302
OpenMP 4.649
PPL 39.811
Amp (ソフトウェアエミュレーション)10分以上

i7(SandyBridge, 2core/4thread) + Radeon HD 6630M

Sort1 2.106
Sort2 1.965
OpenMP 2.200
PPL 14.274
Amp 15.600

5. 適当に考察と補足

奇偶転置ソートでは処理が単純すぎて、並列化のコストの方が大きくなっているようです。

C++ AMPの実行時、GPU負荷は約60%でした。CPUの呼び出しコストの方がボトルネックになっていると思います。

6. 他の並列ライブラリ

Visual Studio単体でできる並列処理ライブラリ以外にも、次のようなものがあります。

Intel TBB(Threading Building Blocks) : Intel製のオープンソース。AMD x86プロセッサでも動く。

Apple GCD(Grand Central Dispatch) : Apple製。OS X Snow Leopardの目玉機能の一つ。

C=(CSTRIPES) : よくわからん。気付いたらOpenCVが対応していた。Windows/Linuxのx86/x64向け。

NVIDIA CUDA : NVIDIA製。GPGPU。Tesla/Quadro/GeForce専用。

Khronos OpenCL : Apple提唱、クロスプラットフォーム。GPGPUも可能。

OpenACC : たぶんNVIDIA提唱。OpenMPのGPU版。


Xcode 4.6でOpenCLを使う

$
0
0

時間がないので簡易メモです。

【手順】

  1. Xcodeを起動して普通にプロジェクトを作る(例えば、コンソールアプリケーション、C++)
  2. Project Navigator(左画面)にあるプロジェクト名部分をクリック
  3. 中央画面上部にある”Build Phases”をクリック
  4. “Link Binary With Libraries”の左にある三角をクリック
  5. “+”をクリックし、ダイアログの中から”OpenCL.framework”を探してAddする
  6. 必要に応じてOpenCLカーネルを記述するためのソースコード(拡張子cl)を追加する

【注意点】

  • インクルードファイルは”OpenCL/opencl.h”。これはMac特有らしいので注意。必要に応じて”#ifdef __APPLE__”マクロなどを使う。
  • C++ APIは用意されていない様子。がっかり。
  • *.clファイルを追加すると、OpenCLカーネルをコンパイルしてバイナリ化する。コンパイルは、CPU x86、CPU x64、GPU 32bitの3種類がターゲットにされ、それぞれ”.i386.bc”、”.x86_64.bc”、”.gpu_32.bc”という接尾語がファイル名に追加される。格納場所は、実行バイナリのあるフォルダを基準に”OpenCL/[オリジナルのOpenCLファイル名][接尾語]“である。
  • このとき、コンパイルエラーもチェックされる。エラーがあれば、Issue Navigatorに表示される(画面左上の△に!のついたアイコンをクリック)。
  • IntelのGPUではOpenCLが実行できない。IvyBridgeのようにハードウェアがOpenCLに対応していても、ドライバが対応していない。がっかり。

-


Direct ComputeとCUDAの同期命令

$
0
0

メモリバリアやフェンス命令について、調べて分かったことのまとめです。ドキュメントの理解が怪しいうえに、実装して実験していないので、間違っている可能性あり

【そもそもバリアが必要なわけ】

データハザード(RAWハザード・WARハザード・WAWハザード)が起きるから。

SIMT型の(≒GPGPUの)並列処理においてバリアがない場合何が起きるか考える。あるスレッドBが別のスレッドAによって書き込まれた値を参照したいシナリオがあったとする。しかし、スレッドAが値の書き込みが終わっているか否かはスレッドBには分からない。したがって、スレッドAによって更新される前の値を参照してしまう可能性がある。更新を確実にするには、スレッドを跨いだ値の参照が起こるよりも前の時点で、同期待ち(バリア)を行えばよい。

【CUDAの場合】

■__syncthread

この命令が実行されるより前のグローバルメモリとデバイスメモリに対するアクセスが完了し(=このスレッドのメモリ書き込みの結果を同じブロック内の他のスレッドが読み出せる状態になり)、かつ同じブロック内の全スレッドがこの命令にたどり着くまで、これ以降の命令について同じブロック内の全スレッドを実行しない

■__threadfence

この命令が実行されるより前のグローバルメモリとシェアードメモリに対するアクセスが完了するまで、これ以降の命令について同じブロック内の全スレッドを実行しない

※グローバルメモリアクセスは(自分のスレッドのメモリ書き込みが)全スレッドに反映されるまで待機、シェアードメモリアクセスは(自分のスレッドのメモリ書き込みが)同じブロック内のスレッドに反映されるまで待機し、両方の待機が解けたら以降の命令を実行する

■__threadfence_block

この命令が実行されるより前のグローバルメモリとシェアードメモリに対するアクセスが完了するまで、これ以降の命令について同じブロック内の全スレッドを実行しない

※グローバルメモリアクセスは同じブロック内のスレッドに反映されるまで待機、シェアードメモリアクセスも同じブロック内のスレッドに反映されるまで待機し、両方の待機が解けたら以降の命令を実行する

■__threadfence_system

この命令が実行されるより前のグローバルメモリ・シェアードメモリ・ページロックメモリに対するアクセスが完了するまで、これ以降の命令について同じブロック内の全スレッドを実行しない

※2GPU間での同期などに利用する

【Direct Computeの場合】

■GroupMemoryBarrier()

この命令が実行されるより前のgroupsharedメモリに対するアクセスが完了するまで、これ以降の命令について同じグループ内の全スレッドを実行しない

※groupsharedメモリのアクセスがなければ、この命令は無意味

■GroupMemoryBarrierWithGroupSync()

この命令が実行されるより前のgroupsharedメモリに対するアクセスが完了し、かつ同じグループ内の全スレッドがこの命令にたどり着くまで、これ以降の命令について同じグループ内の全スレッドを実行しない

■DeviceMemoryBarrier()

この命令が実行されるより前のデバイスメモリ(おそらくUAVなどのBufferのこと)に対するアクセスが完了するまで、これ以降の命令について同じグループ内の全スレッドを実行しない

※デバイスメモリのアクセスがなければ、この命令は無意味

■DeviceMemoryBarrierWithGroupSync()

この命令が実行されるより前のデバイスメモリに対するアクセスが完了し、かつ同じグループ内の全スレッドがこの命令にたどり着くまで、これ以降の命令について同じグループ内の全スレッドを実行しない

■AllMemoryBarrier()

この命令が実行されるより前の全種類のメモリに対するアクセスが完了するまで、これ以降の命令について同じグループ内の全スレッドを実行しない

※メモリアクセスがなければ、この命令は無意味

■AllMemoryBarrierWithGroupSync()

この命令が実行されるより前の全種類のメモリに対するアクセスが完了し、かつ同じグループ内の全スレッドがこの命令にたどり着くまで、これ以降の命令について同じグループ内の全スレッドを実行しない

【推測というか考察というか】

1. __syncthreads()や**MemoryBarrierWithGroupSync()はブロック内の全スレッドがその命令の位置で同期するが、__threadfence()や**MemoryBarrier()は自分のスレッドのみ待機する(GPUはWarp(Wavefront)を最小粒度として並列実行するから、厳密には「自分のスレッドのみ」ではなく「自分のWarp/Wavefrontに属する全スレッドが」待機する)。

2. __syncthreads()はAllMemoryBarrierWithGroupSync()と同じ。ただし、共有メモリの同期についてのみ考えるならば、__syncthreads()はGroupMemoryBarrierWithGroupSync()と同じ。

3. 分岐により一部のスレッドしか__syncthreads()を呼び出さなかったとき、ブロック内の全スレッドが同期するかどうかはわからない。多分同期されないと思う。

【__threadfenceの使い道】

CUDA C Programming Guideに例が記載されていた。他のブロック間でのデータの受け渡しには、__threadfence(あるいはカーネル関数の再立ち上げ)が必要。

【ソース】

MSDN

CUDA C Programming Guide

Microsoft Direct Compute on the 2nd Generation Intel Core processor(PDF)

CUDA II: additional topics(PDF)



Kepler GPUのSIMD命令

$
0
0

KKeplerアーキテクチャ(Compute Capability 3.0)以降のNVIDIA GPUには、SIMD命令が新設されています。

ここでいうSIMDとは、(GPUの典型的な構造である)SMX内で各CUDA Coreが1つのデータに対し1つの処理を行う(広い意味での)SIMDではなく、1つのCUDA Coreが本当に複数のデータを一度に処理するSIMDです。x86におけるSSEのようなものですが、KeplerのSIMDはレジスタ長が32bitです。

Keplerでは、32bitレジスタに格納された「8bit整数×4」か「16bit整数×2」に対してSIMD演算を行うことができます。命令として、加減算、絶対差、比較、平均などが行えますが、乗除算、シフトはありません。

■イントリンシック命令

命令はPTXを直接書くことで利用できますが、それではあまりに不便です。そこで、NVIDIAから提供されている、PTXをイントリンシック命令の形で書くことができる(その上Fermi以前の古いGPUでも一切のコード変更なしに新命令をエミュレーションできる)便利なCヘッダファイルを使います。このファイルをダウンロードするには、NVIDIAのアカウントを作り、CUDA/GPU Computing Registered Developer Programを申請して認証が下りた後に、CUDA Registered Developer ProgramのページにあるCUDA SIMD-within-a-word functionsの右のDownloadボタンを押し、tarを展開します。

tarの中には、イントリンシック命令が定義されたヘッダ、そのサンプルとMakefileが入っています。

■関数一覧

表にまとめました。関数の引数はすべて2つです。詳細はヘッダを参照してください。

参考までに、関数名とそれに対応するPTX命令も書きました。ややこしくなるので16bit命令しか用意していませんが、8bit命令では末尾を4に変えればOKです。(M)は、複数の命令が組み合わされていることを意味します。数字は気にしないでください。

16bit命令 8bit命令 PTX(16bit) - – - 説明
vabs2 vabs4 vabsdiff2 1 絶対値
vabsdiffs2

vabsdiffu2

vabsdiffs4

vabsdiffu4

vabsdiff2 2 差の絶対値
vabsss2 vabsss4 vabsdiff2 1 絶対値(飽和)
vadd2 vadd4 vadd2 2
vaddss2

vaddus2

vaddss4

vaddus4

vadd2 2 和の絶対値
vavgs2

vavgu2

vavgs4

vavgu4

vavrg2 2 平均値(切り上げ)
vcmpeq2

vcmpges2

vcmpgeu2

vcmpgts2

vcmpgtu2

vcmples2

vcmpleu2

vcmplts2

vcmpltu2

vcmpne2

vcmpeq4

vcmpges4

vcmpgeu4

vcmpgts4

vcmpgtu4

vcmples4

vcmpleu4

vcmplts4

vcmpltu4

vcmpne4

vset2(M) 2 比較(全ビットを立てる)
vhaddu2 vhaddu4 -(M) 2 平均値(切り捨て)
vmaxs2

vmaxu2

vmaxs4

vmaxu4

vmax2 2 最大値
vmins2

vminu2

vmins4

vminu4

vmin2 2 最小値
vneg2 vneg4 vsub2 1 符号反転
vnegss2 vnegss4 vsub2 1 符号反転(飽和)
vsads2

vsadu2

vsads4

vsadu4

vabsdiff2 2 差分絶対和
vseteq2

vsetges2

vsetgeu2

vsetgts2

vsetgtu2

vsetles2

vsetleu2

vsetlts2

vsetltu2

vsetne2

vseteq4

vsetges4

vsetgeu4

vsetgts4

vsetgtu4

vsetles4

vsetleu4

vsetlts4

vsetltu4

vsetne4

vset2 2 比較(1をセット)
vsub2 vsub4 vsub2 2
vsubss2

vsubus2

vsubss4

vsubus4

vsub2 2 差(飽和)

注意点として、引数がすべてunsigned intとなっており、符号付整数の場合キャストが必要になります。また、AVXのvbroadcastのように、8/16bit整数を同じ32bitレジスタ内にコピーする命令がありません(__byte_perm()組み込み関数で実現できると思われます)。

■スループット

ドキュメントには特に記載がありません。通常の整数加算と同じスループット(7/8 cycle)だと思われます。だとすれば、SIMDを使えばスループットを2倍・4倍に上げることができ、画像処理・音響信号処理においては非常においしい命令になるはずです。

■まとめ

Keplerに新設されたSIMD命令について紹介しました。Keplerには他にもスレッド間シャッフル命令があるので、機会があれば記事を書く予定です。


NVIDIA Tegra4のOpenGL ES拡張メモ

$
0
0

個人用メモ

■OpenGL拡張(赤字はTegra3にはなかった拡張、☆はOpenGL ES 3.0の必須機能(あるいは互換性のある機能、理解が非常に怪しいので参考程度に))

GL_OES_rgb8_rgba8

GL_OES_EGL_sync

GL_OES_surfaceless_context

GL_OES_fbo_render_mipmap

GL_NV_depth_nonlinear

GL_NV_draw_path

GL_NV_draw_texture

☆GL_NV_texture_npot_2D_mipmap

GL_OES_EGL_image

GL_OES_EGL_image_external

GL_NV_EGL_image_external_YUV

GL_OES_vertex_half_float

GL_OES_mapbuffer

☆GL_NV_draw_buffers

GL_NV_multiview_draw_buffers

GL_EXT_color_buffer_half_float

GL_EXT_packed_float

GL_NV_packed_float

☆GL_EXT_texture_rg

GL_OES_texture_half_float

☆GL_NV_texture_array

☆GL_OES_compressed_ETC1_RGB8_texture

GL_EXT_texture_compression_latc

GL_NV_texture_compression_latc

GL_EXT_texture_compression_dxt1

GL_EXT_texture_compression_s3tc

GL_NV_texture_compression_s3tc

GL_EXT_texture_filter_anisotropic

GL_NV_get_tex_image

☆GL_NV_read_buffer

GL_NV_shader_framebuffer_fetch

GL_NV_copy_image

GL_NV_fbo_color_attachments

GL_EXT_bgra

GL_EXT_texture_format_BGRA8888

GL_EXT_read_format_data

GL_EXT_unpack_subimage

GL_NV_pack_subimage

GL_NV_texture_compression_s3tc_update

GL_NV_read_depth

GL_NV_read_stencil

☆GL_NV_uniform_buffer_object

☆GL_NV_map_buffer_range

GL_EXT_robustness

GL_OES_standard_derivatives

GL_NV_EGL_stream_consumer_external

GL_EXT_separate_shader_objects

☆GL_NV_copy_buffer

GL_NV_3dvision_settings

GL_EXT_debug_marker

GL_EXT_debug_label

GL_KHR_debug

GL_EXT_texture_storage

☆GL_NV_pixel_buffer_object

☆GL_NV_framebuffer_blit

☆GL_NV_non_square_matrices

☆GL_NV_explicit_attrib_location

☆GL_OES_vertex_array_object

GL_NV_smooth_points_line

GL_OES_texutre_half_float_linear

GL_NV_texutre_border_clamp

☆GL_OES_depth_texture

☆GL_OES_depth_texutre_cube_map

GL_NV_shadow_samplers_cube

☆GL_NV_shadew_samplers_array

☆GL_EXT_shadow_samplers

☆GL_OES_depth24

GL_EXT_sRGB

GL_EXT_texture_sRGB_decode

GL_NV_framebuffer_sRGB

GL_NV_generate_mipmap_sRGB

GL_NV_sRGB_formats

☆GL_EXT_occlusion_query_boolean

GL_NV_occlusion_query_samples

GL_NV_timer_query

☆GL_NV_framebuffer_multisample

GL_EXT_frag_depth

☆GL_NV_instanced_arrays

☆GL_NV_draw_instanced

GL_NV_secure_context

GL_NV_packed_float_linear

□Tegra4から消滅したOpenGL拡張

GL_EXT_Cg_shader

GL_NV_coverage_sample

□OpenGL ES 3.0にあってTegra4にない機能

ピクセルシェーダの32bit精度

トランスフォームフィードバック

頂点テクスチャフェッチ

3Dテクスチャ

MSAAのcentriodサンプル

フラットシェーディング

EXT2/EATC圧縮

GLSL ES 3.0

■EGL拡張(赤字はTegra3にはなかった拡張)

EGL_ANDROID_image_native_buffer

EGL_KHR_create_context

☆EGL_KHR_fence_synce

EGL_KHR_stream

EGL_KHR_surfaceless_context

EGL_NV_native_query

EGL_NV_system_time

EGL_EXT_buffer_age

EGL_IMG_context_priority

EGL_KHR_gl_renderbuffer_image

EGL_NV_perform

EGL_KHR_stream_producer_eglsurface

EGL_KHR_lock_surface

EGL_NV_post_convert_rounding

EGL_KHR_image_base

EGL_KHR_gl_texture_cubemap_image

EGL_KHR_gl_texture_2D_image

EGL_KHR_stream_fifo

EGL_KHR_stream_cross_process_fd

EGL_KHR_image

EGL_KHR_image_pixmap

EGL_NV_depth_nonlinear

EGL_KHR_config_attribs

EGL_KHR_reusable_sync

EGL_NV_3dvision_surface

EGL_NV_multiview_window

EGL_NV_stream_sync

EGL_KHR_stream_consumer_gltexture

EGL_EXT_create_context_robustness

□Tegra3から消滅したEGL拡張

EGL_KHR_get_all_proc_address

EGL_ANDROID_recordable

EGL_ANDROID_presentation_time

■glGetIntegerv()の値(大事そうなやつのみ)

GL_MAX_FRAGMENT_UNIFORM_VECTORS : 1024

GL_MAX_VERTEX_UNIFORM_VECTORS : 280

GL_MAX_VARYING_VECTORS : 15

GL_MAX_VERTEX_ATTRIBUTES : 16

GL_MAX_TEXTURE_UNITS : 16

GL_MAX_VERTEX_TEXTURE_UNITS : 0

GL_MAX_TEXTURE_SIZE : 4096

GL_MAX_VIEWPORT_DIMS : 4096 x 4096

GL_SUBPIXEL_BITS : 4


WindowsかMac OS XでOpenGL事始め

$
0
0

OpenGLフレームワークであるGLFWと、OpenGL拡張APIの使用をサポートするGLEWと、OpenGL向け算術関数ライブラリであるGLM(今回はダウンロードだけ)を使い、Visual Studio 2013 ExpressとXcode 5.0でOpenGLでプログラムを書くまでの手順です。

自分向けのメモです。初めにWindowsでの手順を書き、次にMacでの手順を書きます。WindowsではVisual Studioの使い方は省略しています(調べればすぐ分かると思います)。

—–

【GLFW】

wglCreateContext()とかwglMakeCurrent()とかプラットフォーム固有の面倒な初期化処理をラップして扱うために、GLFWは非常に便利です。昔はGLUTが有名でした。

公式の安定版ダウンロードはここです。Visual Studio 2010 / 2012用はこれを使えばよいです。しかし、現時点でVisual Studio 2013用のバイナリがないので、自分でビルドします。ビルドにはCMakeが必要です。

GitHubのリポジトリはここです。安定版であるGLFW 3.0.3のタグはここです。Visual Studio 2013からGitをサポートした(らしい)のですが、CMakeでビルドするまでVisualStudioでは開けない(はず)なので気を付けてください。面倒な人は画面右下の”Download ZIP”を押せばソースコードがzipで降ってきます。

ソースコードを置く場所を決めて展開・移動させ、CMakeを開き、Configure & Generateします。対象のコンパイラは”Visual Studio 12″です。オプションで、DLLを作ったり、WGLの代わりにEGLを使ったりすることができます。

CMakeでビルドしたフォルダにある”GLFW.sln”を開き、DebugとReleaseの構成でビルドします。”0 失敗”なら成功です。試しにx64でビルドしたら失敗しました。ライブラリが”src/(Debug|Release)/glfw3.lib”にあります。動作確認のための実行ファイルも”tests”や”examples”っフォルダにあるので、必要に応じて試します。

GLFWはzlibライセンスです。ソースコードの配布も、ライセンス表示も不要です。

■Xcodeでは

CMakeでビルドするところまでの手順は同じです。

CMakeビルド後、”GLFW.xcodeproj”を開き、DebugとReleaseの構成でビルドします(構成の変更はcommand+shift+<キーを押し、Build Configurationを変更します)。ライブラリが”src/(Debug/Release)/libglfw3.a”にあります。動作確認のための実行ファイルも”tests”や”examples”っフォルダにあるので、必要に応じて試します。

また、Schemeを”ALL_BUILD”から”install”に変更し、同様にビルドすると、/usr/localディレクトリにインストールされます。アンインストールはSchemeを”uninstall”に変更します。

【GLEW】

Window SDKにはOpenGL 1.x(1.1とか1.3とか1.5とか聞くけど正解がどれか知らない)までのAPI定義しかなく、それ以降はwglGetProcAddress()で一つ一つ関数ポインタを取得する必要がありますが、GLEWはOpenGL 4.4を含む最新のOpenGLのAPIとグラフィックスドライバ固有のAPIをC/C++から簡単に呼び出せる形にしてくれます。

公式の安定版ダウンロードはここです。Visual C++6 / Visual Studio 2010用はこれを使えばよいです。しかし、現時点でVisual Studio 2013用のバイナリがないので、自分でビルドします。

GitHubのリポジトリはここです。安定版であるGLEW 1.10のタグはここです。…しかし、GNU MakeやPerlがないとglew.cが生成されないようで、ビルドが通りません(OpenGL拡張のtxtから動的にヘッダを生成しているのでしょうか)。MSYSを使うこともできますが、面倒なので代わりに公式サイトトップにソースコードが置いてあるので、そちらを使います。

ソースコードを置く場所を決めて展開・移動させ、”build/vc10/glew.sln”を開き、C++コンパイラとライブラリをアップデートします。ビルド構成にある”Debug MX”と”Release MX”は、マルチスレッド対応版です(今回は使わない)。

普通にビルドすると”error RC2102: string literal too long”でリソースコンパイルに失敗します。そこで、リソースファイルを編集します。”build/glew.rc”を開き、”Mesa 3-D graphics”の直前にダブルクオート(「”」←これ)を2つ挿入し、さらにその2つのダブルクオートの間に改行を入れてから保存します。これでビルドできます。ライブラリが”lib/(Debug|Release)/Win32/glew32**.lib”に、DLLが”bin/(Debug|Release)/Win32/glew*.dll”にあります。

スタティックリンクライブラリを使うには注意が必要です。この状態ではGLEWの関数が一切利用できません。これは、glew.hで関数に__declspec(dllimport)修飾子がついてしまうためです。修正するには、GLEWを利用するプロジェクトのソースコードでglew.hをインクルードする前に”#define GLEW_STATIC”を定義するか、プロジェクトのプリプロセッサの定義にGLFW_STATICを追加します。[参考文献1]

GLEWは修正BSDライセンスなので、ソース・バイナリの配布時にライセンスを記したファイルを同梱してください。

■XCodeでは

ダウンロードするところまでの手順は同じです。XcodeのCommand Line Toolをあらかじめインストールしておいてください。

ターミナルでglewディレクトリ内のMakefileがある場所に移動し、”make all”コマンドを実行します。デフォルトでRelease(というか-O2)でビルドされるようで、静的ライブラリと共有ライブラリが、シングルスレッド版とマルチスレッド版両方それぞれ出力されます。

“sudo make install”で/usrにインストールされますが、なぜかglew.hもlibGLEW.aもnot foundになってしまいます。原因はよく分かりませんが、stackoverflowによると、/usr/localにインストールすると正しくビルドできるそうです。”sudo make install GLEW_DEST=/usr/local”とすることで、正しくビルドできるようになりました(sudoは必要ないかもしれません)。

他のmakeオプションは公式サイトに書かれています。

—–

【GLM】

DirectX MathのOpenGL版です。SIMDにも対応し、CUDAからも読み込めます。

公式の安定版ダウンロードはここです。GitHubのリポジトリはここです。testはCMakeでのビルドが必要ですが、利用するためのAPIはヘッダファイルのみで構成されており、ビルドは必要ありません。単にインクルードパスを指定するか、自分のプロジェクトに同梱するだけで使えます。

GLMはMITライセンスなので、ソース・バイナリの配布時にライセンスを記したファイルを同梱してください。

—–

【動かしてみる】

ちょうどいいタイミングでもんしょの巣穴さんがGLFWのサンプルを書かれていたので[参考文献2]、アレンジを入れつつGLEW込みで使えるよう改変しました。

多々手抜きがあるのはご愛嬌。とりあえず青いウィンドウが出ればOKです。無理矢理GLEWを使うために、glBeginQuery/glEndQuery()を呼び出しています。OpenGL 3.2以降を使うときは、コメントアウトされているプロファイルを指定してください。

// OpenGL test
#define GLEW_STATIC

#include <stdio.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>

#ifdef _WIN32
#pragma comment( lib, "glfw3.lib" )
#pragma comment( lib, "opengl32.lib" )
#ifdef NDEBUG
#	pragma comment( lib, "glew32s.lib" )
#else
#	pragma comment( lib, "glew32sd.lib" )
#endif
#endif // _WIN32

#define SCREEN_WIDTH (800)
#define SCREEN_HEIGHT (600)

static void error_callback(int error, const char* description)
{
	fputs(description, stderr);
}

static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
	if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
	{
		glfwSetWindowShouldClose(window, GL_TRUE);
	}
}

static void init()
{
}

static void paint()
{
	glClearColor(0.0f, 0.0f, 0.5f, 1.0f);
	glClearDepth(1.0f);
	glClearStencil(0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

	glEnable(GL_CULL_FACE);
	glCullFace(GL_BACK);

	glBeginQuery(GL_TIME_ELAPSED, 1);
	glEndQuery(GL_TIME_ELAPSED);
}

int main(int argc, char* argv[])
{
	glfwSetErrorCallback(error_callback);
	if (!glfwInit())
	{
		return -1;
	}

	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
	glfwWindowHint(GLFW_RED_BITS, 8);
	glfwWindowHint(GLFW_GREEN_BITS, 8);
	glfwWindowHint(GLFW_BLUE_BITS, 8);
	glfwWindowHint(GLFW_ALPHA_BITS, 8);
	glfwWindowHint(GLFW_DEPTH_BITS, 24);
	glfwWindowHint(GLFW_STENCIL_BITS, 0);
	//glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
	//glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
	glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
	GLFWwindow* window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "GL Sample", NULL, NULL);
	if (!window)
	{
		glfwTerminate();
		return -1;
	}

	glfwMakeContextCurrent(window);
	glfwSetKeyCallback(window, key_callback);
	glfwSwapInterval(1);

	auto glewErr = glewInit();
	if (glewErr != GLEW_OK)
	{
		puts((const char*)glewGetErrorString(glewErr));
		return 1;
	}

	init();

	while (!glfwWindowShouldClose(window))
	{
		paint();
		glfwSwapBuffers(window);
		glfwPollEvents();
	}

	glfwDestroyWindow(window);
	glfwTerminate();
	return 0;
}

Visual Studioでは、インクルードパスとライブラリのディレクトリを指定してくださ(動的リンクのときは”#define GLEW_STATIC”をコメントアウトし、DLLにパスを通す)。

■Xcodeでは

プロジェクトの”Build Settings”の”All”を押し、”Search Paths”の”Header Search Paths”に”/usr/local/include”を追加し(入力欄ダブルクリックして+を押す)、”Library Search Paths”に”/usr/local/lib”を追加します。

次に、”Build Phases”に切り替え、”Link Binary With Libraries”に”CoreVideo.framework”、”IOKit.framework”、”Cocoa.framework”、”OpenGL.framwework”を追加します。そして、ファインダーで”/usr/local/lib”に移動し(ターミナルを開いて”open /usr/local/lib”と入力するのが楽[参考文献3])、”libGLEW.a”と”libglfw3.a”をドラッグ&ドロップします。

——

【まとめ】

OpenGLでプログラムを作るまでの準備を行いました。

TODO: GLMを使ったモデル表示、GLEWの完全自前ビルド

——

【補足:Mac OS XでOpeGL 3.2以降を利用するには】

glfwCreateWindow()の前に次の指定が必要です(この指定がなければ、OpenGL 2.1以前しか利用できません。床井先生様様です)。


glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

Intel HD Graphics 4000 + Mac OS X Mavericks(10.9)の環境で、OpenGL 4.1が使えることを確認しました。ちなみに、MacでのGPU別の利用可能APIの一覧はAppleのDeveloperサイトにあります。

——

【参考文献】

  1. GLEWのスタティックリンク(静的リンク)ライブラリの使用方法、Xeo Notes
  2. WindowsでOpenGLを使うために、もんしょの巣穴
  3. ゲームグラフィックス特論 第1回 講義ノート、Kohe Tokoi

技術系Advent Calender 2013の個人的お気に入り記事

$
0
0

今年もやりますAdvent Calender勝手にまとめ。99%個人用です。1%の気の合う他人のために公開します。

今回は去年と違って時間がないのでかなり適当です…

—-

Android Advent Calender】リンク

NDKのndk_helperモジュールを使おう
NDK r9bにAPI呼び出しを簡単にするライブラリが追加されたお話。というか作者さん?シェーダコンパイラや算術ライブラリはiOSとの互換性を考えると使いにくいけど、ジェスチャーは便利そう。

Gmailの宛先欄みたいなチップ上のテキスト (Chips Edit Text)を実現する
EditTextにアイコン+装飾文字列を複数並べて表示する方法。ライブラリ化したソースコードもあり。

バターナイフの用法とその効果
Butter Knifeを使ってfindViewById()やonClick()等を簡単に記述する方法の紹介

Google Cloud Messagingでハマったこと

本気でAndroid用のアイコンを作る
公式アイコンの分析がすばらしい

感想:MavenやGradleという用語が何度も登場していますが、Antに代わるビルドシステムだそうです。初めて聞きました。時代に取り残されていますね。

 

C# Advent Calender】リンク

メタプログラミング入門 – Roslyn による C# ソースコードの解析と変更
最近構文解析まわりが熱いのでメモ

GDI+で描画&保存あれこれ
最近フォントレンダリングまわりも熱いのでメモ。案外シンプル

CSharpCodeProvider + MEFで実行時に生成したDLLを簡単に扱う
MELというプラグイン?を作るフレームワークがあるらしい

.NETの動的コード生成技術の紹介

C#最履修者向けブックガイド
『自分が知らないからって、自分がコーディング規約を作る立場だからだといって「LINQ禁止」だとか、「ラムダ禁止」とかして、若い人たちをを苦しめていませんか?ワケわからないから禁止。…それじゃ、あなたも私も20代や30代前半で嫌っていたあの「老害」です。…あなたたちが戦う相手だった「老害」になってどうするんですか。』

 

C++ Advent Calender】リンク

C++14 時代の constexpr プログラミング作法
もう中3女子さんがconstexpr対応コンパイラ書けばいいのではないか

スレッドセーフという幻想と現実
とても詳細

構文解析ツールとしてClangを使ってみる
最近構文(ry

VisualStudio2013NovCTP : C++17(予定)resumable/await紹介
async/awaitのC++版

C++でターミナルに画像を表示させる
ちょうどboost:gil画像読み込みしようと思っていたのでメモ

本当に怖いC++erとC++という糞言語
「あー、C++って新しいCことだよね、知ってる知ってる」←まるでわかってない

 

C++ (fork) Advent Calender】リンク

並列処理
Concurrency Runtimeを使った非同期処理すごい

C++11の乱数ジェネレーターを自作してみた
xorshift

 

Git Advent Calender 2013】リンク

社内にGITを持ち込むために上の人を納得させるセリフ集
『それにSVNのチェリーピックを露骨に危険&手間とアピールしていけばgitの重要性は認識してもらえるはず。』
ほんとこれ。残業に関わるので、本当に勘弁してほしい。

黒い画面に不慣れな同僚にGitを使ってもらう為のGitクライアントGitHub for Mac (and Windows)
私もSourceTreeよりGitHub for Mac派

 

HTML5 Advent Calender 2013】リンク

WebRTCに使われるP2Pの技術
ブラウザ同士で通信する仕組み

 

iOS Advent Calender 2013】リンク

「顔以外」のものを画像認識する
OpenCVを使った犬猫検出など

xcassetsでresizable imageのコードを駆逐する

iPhoneで取得・検知できる情報10連発!(サンプルアプリもあるよ)

かゆいところに手が届きそうなAVFoundationとMediaPlayerによる音楽再生アプリ作成メモ
サウンドとiOSの機能との連携

 

Java Advent Calender 2013】リンク

Java8 Stream APIを学ぶ
LinqがJavaにもきた

Stream APIの使い方
シリアライズも便利になりそう?

日本人のためのDate and Time API Tips
いい意味で、PHPっぽい

JDK 8 新機能ダイジェスト (JDK 8 Features)
x86最適化興味ある。どこかに情報ないかな

 

JavaScript – Client Side – Advent Calender 2013】リンク

Dropbox Datastore APIの使い方とか色々
認証のやり方から解説。『Operaが記載されていませんが、Operaでも使えます。』

Three.jsで究極小宇宙爆誕
WebGL

 

カーネル/VM Advent Calender 2013】リンク

stable kernel reviewに参加してみませんか
面白そう

F2FS(Flash-Friendly File System) を試してみる。
SSD向ファイルフォーマットの話

 

Linux Advent Calender 2013】リンク

超高速bashオペレーション
すごい。Macでもできた。これは便利

 

Perl Advent Calender 2013】リンク

Perl meets GPU
PerlでCUDA!!C/C++ではなくPerlだけでカーネル関数呼び出しができちゃう最高にCOOL! COOL! COOL!な記事。が、ActivePerlで動かすのは面倒そう

 

PHP Advent Calender 2013】リンク

PHPの配列を使った手品とその種明かし
きもちわるい!

NULLのAND/ORにはめっちゃ気をつけて!
きもちわるいで!

PHPが糞言語なのはどう考えても参照をポインタだと思っているお前らが悪い
PHPの参照はCのポインタとは違うという話。

初心者向け タイプヒンティングとはなんなのかというお話
ここまできたら強い型付けの言語(C#やJava)で書いたら?とも思うが、素晴らしいテクニックだと思う

Raspberry Pi と PHP で遊ぼう
PHPでGPIOを操作

PHP 文字列リテラルにおける変数展開ノ全テ
きもちわるい!

+n month の罠
1日を起点にしなければ意図しない結果になるという話

 

PHP Advent Calender 2013】リンク

PHP5.4のtrait機能を理解する
RubyのMix-in。最近までMix-inなんて何に使うのか疑問だったけど、お仕事プログラムで継承関係が複雑になってくると有効なのかなと思うようになってきた。

PDOでの数値列の扱いにはワナがいっぱい
PDOでの数値列の扱いにはワナがいっぱい(2)
SQLのエスケープネタは尽きない。総本山の徳丸先生のサイトはおすすめ

PHPのissetの罠
きもちわるい!配列の要素にいきなりis_set()を使うのはやめたほうがよさそう。コメント欄の議論も有用

 

Python Advent Calendar 2013】リンク

iOS実機のSSL通信をプロキシによって傍受したり改ざんする方法
あまりPython関係ない。串の証明書をiPhoneにインストールし、mitmproxyを使えばリアルタイム書き換えもできる、と。便利だけど怖いなぁ。自演Man in the Middle攻撃。

 

Python Advent Calender 2013】リンク

年末大感謝祭!初心者脱出のためのPythonTipsを50個紹介

これ、どこから来てんのよ?
スパマーがどこから来ているかをIPアドレスを使ってGoogle Earthに表示。裏事情が読み物として面白い。

部活をPythonで立て直す
『とりあえず(むちゃくちゃですが)Windowsを全廃してUbuntuにして,ゲームができないようにしました.これはとりあえず効きました』すげーなこの行動力。高1にして将来有望。

sklearnで手書き文字認識
OpenCVなくてもここまでできちゃうのか

 

Ruby Advent Calendar 2013】リンク

今年こそRubyを始めたいあなたに!ももんが流・最強のRuby学習法
これどう思いますか?私はRubyを勉強するぞーと思ってRPGツクールXPを買ったものの、1週間で挫折しました。

Ruby 2.1.0 に追加される不正なバイト列を除去する String#scrub の紹介
まとめると、utrf8からutf8への変換は何も起きない(不正なバイト列を残す、が今はバグで除去される)→utf16を間にかませることで回避→scrubというイカしたメソッドができた

 

TDD Advent Calender 2013】リンク

TDD って何だっけ? #tddadventjp
Red→Green→Refactor

レガシーテストコード改善ガイド #TddAdventJp
ここで紹介されている本は有名。欲しい

 

Unity Advent Calender 2013】リンク

手抜きしてインスペクター拡張

JavaでAndroidアプリを作っていて,今はC#でUnityゲーム作っている自分のC#のメモ(長め)
C#歴よりJava歴のほうが長い私のような人間にオススメの記事

オレオレAssetをAssetStoreに出して死なないために気をつけること
『自分は、少なくとも月の食費は賄えている。』まじかよUnityやろ

Unityでケーキのロウソクの火(物理)を消してみた
スカートめくりはよ

 

Windows Store Advent Calender 2013】リンク

.NET Framework APIの型をWindows Runtime APIの型を変換する

ストアアプリのターミネーターに対処せよ!(事件編)
ストアアプリのターミネーターに対処せよ!(解決編)
Store Appのライフサイクル

Xamlが分からないならメニューエンジン書けばいいじゃない

 

XAML Advent Calendar 2013】リンク

カスタムBehaviorで条件分岐をする

—–

(これから追加予定)

■まとめ

Advent Calenderを一気読みするのがこんなに疲れるとは思わなかった…何度挫折しかけたか…もうやめよう…

Advent Calenderのご利用は計画的に…


NVIDIA Tegra K1のCPUとGPUのスペック

$
0
0

2014 CESでNVIDIAから(Tegra5と思われていた)Tegra K1のスペックが少し公開されたので、まとめました。

【重要】情報の信頼性は保障しません。

Tegra4の時の記事はこちら

ソース:http://www.nvidia.co.jp/object/tegra-k1-processor-jp.htmlhttp://www.nvidia.com/object/tegra-k1-processor.htmlhttp://blogs.nvidia.com/blog/2014/01/05/nvidia-rips-the-lid-off-tegra-k1-demos-64-bit-mobile-processor-running-android/

—–

■SoCスペック比較

SoC Tegra3 Tegra4 Tegra K1 (64bit)
ISA ARMv7 ARMv7 ARMv8(aarch64)
FPU ISA VFPv3 VFPv4 VFPv4
製造 TSMC 40nm LP/G TSMC 28nm HPL TSMC 28nm HPM
CPU Cortex-A9 r2 Cortex-A15 Denver
コア数 4 4 2
クロック[GHz] 1.21.6(boost 1.31.7) 1.9 2.5
L1キャッシュ(I/D) 32kB(4way,32B/line) +32kB(4way,32B/line) 32kB(2way,64B/line) +32kB(2way,64B/line) 128kB +64kB
L2キャッシュ 1MB 2MB(16way) ?
デコード(inst/cycle) 2 3 ?
発行(inst/cycle) 4 8 ?
実行ポート数(うちALUポート) 4(3) 8(3) ?(7)
省電力CPU Cortex-A9 Cortex-A15 なし
GPU ULP GeForce ULP GeForce Kepler
ALU Vertex 4 + Pixel 8 Vertex 24 + Pixel 48 192
クロック[MHz] 520 672 約950
GFLOPS 12.5 96.8 365
Direct3D 9 level 1 9 level 1 11.0
OpenGL ES 2.0 2.0 3.0
OpenGL NA NA 4.4
メモリ DDR3L / LPDDR2 DDR3L / LPDDR2 / LPDDR3 DDR3L / LPDDR3
クロック[MHz] 1500 1866 2133
バス 32bit 64bit 64bit
帯域[GB/s] 6.0 14.9 17
容量 (up to)2GB (up to)4GB (up to)8GB

—–

Tegra K1には2種類あり、CPUが4+1コアCortex-A15 r3ベースのものと、NVIDIAオリジナル設計の64bit CPUであるコードネームDenverコアを2コア搭載したものがあります。GPUコアはPC向けGPUであるGeForce 600シリーズをベースにしたもので、Tegra 2~4のGeForce 6ベースのアーキテクチャとは異なります。TDPは5W、32bit版が2014年上半期、2014年下半期に出荷予定です。

CPU/GPUの性能はPS3やXbox360を超え、GFXBenchのスコアがAppleが開発したApple A7 SoCより2.5倍高いことをアピールしました。

Huang CEOのプレゼンでは、Unreal Engine 4を動作させたり(物理ベースシェーディングやGI、物理シミュレーション)、64bit版Androidが動いている様子を見せたり、よくわかりませんが車のデモを見せました。

—–

■GPUがKeplerベースとなることの利点

もしGeForce 6xxから機能削減されていなければ、モバイルGPUは非常に面白くなってきます。演算精度は24bitからMax 64bitまで上がり、ジオメトリシェーダを使ったGPUベースの布・パーティクルシミュレーション、テセレーションを使ったLoDシステムの実現、Deffered RenderingやForward+といった最近人気のテクニックが全部使えます。CUDAも動くので、物体認識、流体シミュレーション、暗号処理など、応用範囲がけた違いに広がります。

ちょっとメモリ帯域がぎりぎりかなとも思いましたが、新GeFroce GT630が384コアで64bit DDR3-1800なので、192コアなら耐えきれそうです。

—–

■GPUクロックは約950MHz?

性能評価の手がかりとなりそうなのがこのスライドです。単位が馬力(Horsepower)でよくわかりませんが、下の頭でちょっと隠れているところを見ると、GPUはGFLOPS、CPUはSPECIntのスコアだそうです。

おさらいですが、Xboxは48個の4way SIMDなので、48(SIMD)*4(way)*2(MAD)*500(MHz)=240(GFLOPS)です(超越関数は考慮しない)。PS3はピクセルシェーダが24(SIMD)*4(way)*2(Unit)*2(MAD)*500(MHz)=192(GFLOPS)です。なぜか頂点シェーダの計算能力が図に入っていないようですが、大人の事情なのでしょう。

Tegra K1のクロック周波数を求めてみましょう。Tegra K1は365GFLOPSであると書かれているので、192(Core)*2(MAD)*x(MHz)=365(GFLOPS)という式が成り立ちます。xを解くと、950.52…という値が得られます。950MHzというのはモバイルにしては異様に高い値(というか過去の全モバイルGPUの中でトップ?)で、例えばAdreno 320を内蔵するSnapdragon 800は400MHzです。本当にこれが5Wで動くというのが信じられないのですが、とにかく計算上は950MHzです。

—–

■DenverコアのTegra K1はモバイルにもたらされるのか

驚いたことに、Denverコアはやたらリッチなスペックです。1コアあたりのL1命令キャッシュだけで128kBのCPUなんて見たことがありません。パイプライン段数がPentium4のように膨大になりそうな気がするのですが、大丈夫なのでしょうか。

“7-way Superscalar”という表記は少し曖昧な書き方ですが、幸いにも比較としてCortex-A15が3wayと書かれています。Cortex-A15の実行ポートは8つありますが、単純な命令を実行するSimple Clusterが2つ、乗算を実行するMultiply Accumulateが1つあるので、合計して3という計算でしょうか。もしかしたらSimple ClusterとBranch 1つを足して3かもしれませんが、可能性は低いと思います。ということは、ロードストアやSIMDを除いたALUポートが合計7つあることになり、ロードストアやSIMDを含めれば10ポートを超えそうで、スパコン用CPUであるPOWER7の12ポートに迫りそうです。

こうなってくると、本当にモバイルとして耐えうる電力なのかどうか疑問です。シングルスレッド性能を重視して、メニーコア化ではなくビッグな少数コアにする方針はApple A6/A7と同じであり、間違っていないとは思いますが、以前NVIDIAは「Project DenverはHPC向けで、Tegraにはもたらされない」と言っていましたし、難易度が高いように思えます。

そもそもSoCが5Wという時点でスマートフォンに乗せられるレベルではなく、TDP 4W / SDP 2WのIntel Atom Z3740を超える消費電力になります。となると、ひとつ考えらえるのは、クロック(と電圧)を下げたモデルを主流とし、電源が十分に確保できる組み込み機器でのみフルスペックで動作する、という方針です。最悪、GPUコア数を減らしたモデルが出てくるかもしれません。それならTegra4でいいじゃん、というお話になりそうですが。

—–

■じーしんく?じーぴーゆーくらうど?

そんな発表もあったような気がします。フランスからリアルタイム配信でアクションゲームを動かすのはすごいとおもいました(小並感)

—–

走り書きレベルですがTegra K1についてまとめました。まだWhitepaperが公開されていないようなので、公開されたら修正or追記するかもしれません。

—–

■追記1

先に後藤さんに記事を書かれてしまったようです

メモリがLPDDR3-2133 64bitと判明したので、表に書き足しました。GK104からの変更点は、今のところテクスチャユニット半減のみ分かっています。128kB L2キャッシュもそのまま載せてきたのはちょっと驚きです。

一方気になった点が2つあります。プレゼンと違い、消費電力が2Wと書かれています。32bit版だけのなのか、Denverでもそうなのかはわかりません。また、「Keplerアーキテクチャでは、テクスチャパスもロードに使うことが容易になっている」とありますが、これはGK110ベースのCompute Capability 3.5でのみ対応しています。GPUブロック図のSMXにUniform Cacheがあるので、これはGK104をベースにしたComptue Capability 3.0相当のはずで、Tegra K1には当てはまらないのではないかと思います。


Viewing all 40 articles
Browse latest View live