2010年09月08日

オーバクロックとメモリ性能

dingoo A320 で使われているのが、Jz4740。180nm プロセスルールで、仕様では、360MHz。DINGUX では、クロックを変更できて 400MHz 前後まではクロックを上げられるらしい。メモリは、SDRAM 32bit アクセス。SDRAM のクロックは、CPUのクロックの 1/3 が普通で、400MHz なら 133MHz 。

それに対して、Jz4725B は、160nm プロセスルール。 データシートではやはり 360Mhz になっている。メモリは、SDRAM 16bit アクセスしかできない。

前に書いた内容の焼き直しだが、同じクロックの場合、どれぐらい性能的に不利なのか考察してみよう。


    Jz47xx の場合、キャッシュラインのサイズは Iキャッシュ/Dキャッシュ共に 32 バイトなので、通常 32バイト単位での READ/WRITE になる。
     - Linux で CONFIG_MIPS_L1_CACHE_SHIFT=5 という風に設定しているし、32 バイトなのは間違いない。

    そして、Programmers Manual に CPU がどのようなアクセスをするかの記載がある。

      SDRAM は、1,2,4,8-beat の burst アクセスができる。32bit アクセスなら 1 回のアクセスで済むわけだ。16 bit アクセスの場合 たぶん 2 回の 8-beat アクセスをする。ただし、2 回目は 同じ ROW なので少し速い。

      CL=3 だとして、32bit アクセスの場合 32 byte の READ/WRITE は 16/15 クロック。16 bit だと 16 クロック+11/12 クロック。

      • CL=2 の場合、READ -2/WRITE -1 にできる。(同じ ROW なら READ -1/WRITE 0)。 166MHz 品の SDRAM を使っている場合、133MHz CL=2 が可能(な場合が多い)。
        ここは、133MHz CL=2 を前提にする。
      • 32bit アクセスは 14 クロック、16bit アクセスは、25 クロック。


      そうすると 32 bit アクセスの Jz4740 に対して Jz4725B は最大 25/14 = 1.79 -- 1.79倍 遅いことになる。ただし、まったくキャッシュにヒットしない場合の性能差。

        帯域に変換してみよう。133MHz のクロックで ずっと 2バイト読み込めるとすれば、254MB/sec 。32 bit アクセスの場合 254 * 16/14 = 290MB/sec 。16 ビットなら 254 * 16/25 = 163 MB/sec 。

      では、実際はどれぐらい違うのか?

      仮に n% ヒットするとする。

      100 命令実行し キャッシュがヒットした場合 1 クロックで実行できているとする。(100 - n) 個の命令は、メモリアクセスの分待たされるとする。そして、メモリアクセスは、追い出して読み込む動作とする。さらに、SDRAM のクロックは、CPU クロックの 1/3 に設定されているとする(CPU 400MHz に対して SDRAM 133MHz)。

      100% なら 100 クロックで終わるところが...

      32 bit アクセスの場合は、14 * 2 * 3 * (100 - n) クロック 余分に時間がかかる。 16 bit なら 25 * 2 * 3 * (100 - n) クロック。

      n が 99 なら 184:250 。99.9 なら 108.4:115.0。
      n が 90 しかないとすると 940:1600 。

      動画の再生のヒット率は、かなり高いとは思うが、よくは分からない。仮に 90% だとすると Jz4725B は、1.36 倍 遅いことになる。99% なら 1.06倍 。


    さて、最大のクロックは プロセスルールに比例するとする。

    Jz4740 の 180nm に対し Jz4725B は 160nm だから Jz4740 が 400MHz なら Jz4725B は 450 MHz 。1.13 倍 速い。

    速く動かしたいソフトのヒット率が 99% ぐらいなら相殺できそうな感じ。-- でもそううまいこと行くかどうか。

    いろいろ眉唾ものの仮定を入れているので、結論も眉唾だが、必要なデータが揃えば大分分かってくるとは思う。-- ただ、そのときは結果が分かっているはず。上記の考察は結果を分析するとき役にたつ程度だろう。

    他の見方をしてみよう。90% しかヒット率がなければ、32 bit アクセスでも 940 クロックかかる。これが 99% にできると 184 クロックで済む。実に 5.1 倍も速くなるのだ。

      32bit アクセスでも メモリアクセス 1 回が 84 CPU クロック。チューニングに於いては、まずメモリアクセスを減らすのが重要だ。

    さらに言うと十分チューニングされた(動画とかエミュレータ)ソフトなら 90% しかヒット率がないということはないはず。もし、90% だったら オーバクロックに期待するより真っ当にチューニングしたほうが良い。

    ただし、ブラウザとか巨大ソフトは例外。遅くともチューニングしきれないし.. そもそも動かそうとするのが間違っていると考えることにしよう。

    ちょっと動画について考察

      IPU を使うとして、動画のためにどれぐらいのメモリ帯域を使うのだろう?
      640x360 のデータを YCbCr(4:1:1) として 30fps で出力するとする。640x360x30x (4+1+1)/4 = 10MB/sec これは read-write になるから 帯域としては x2 の 20MB/sec 必要。入力は1/10 に圧縮されているとすれば、1MB/sec 。
      で、前のフレームを参照するとすれば、10MB/sec でも読み込む。(こちらはダーティにしないので 帯域も 10MB/sec)
      残りが全部キャッシュに載るはずはないのだが .. ここまでで 31MB/sec 。ちなみに IPU を使って 400x240 R5G6B5 に展開しているとすれば、読み込み 10MB/sec , 書き出し 5.8MB の帯域を脇で使っていることになる。さらに、フレームバッファも 5.8MB/sec で読み込んで 外部に出力している。入力データ 1MB/sec も どこかから読んで DMA で WRITE しているはずなので 足しておこう。
      そうすると CPU の邪魔をしている要因として 22.6 MB/sec の帯域が使われている計算になる。

      ここまでで、使っているメモリ帯域は、53.6 MB/sec 。全部で 163 MB/sec しかないのだから結構な割合だ。

      キャッシュには Iキャッシュもある。16KB しかないから当然足りないのだが、処理ブロック毎にループしているはずで、1 ループで載り切らないことがない限り問題にしなくとも良い。

      あとは、データ。ワークとして使う領域がある。16KB しかないキャッシュに載るとは思えないが、あまり メモリとの出し入れが多いと メモリ帯域を食いつぶしてしまう。さらに カーネルやら サウンド処理やら動いているわけで、余ったメモリ帯域で 動いてくれないといけない。

      ざっと見て相当に厳しそうだ。Jz4755 などは、32bit アクセスで 768p が再生できるとしているので メモリ帯域が足りなくなる とはあまり思わないのだが ... 相当にチューニングしないと Jz4725B で 360p の再生は難しいのではないかと思えてきた。

      もちろん CPU として、能力が足りているかどうか という問題もあるのだが、キャッシュにデータが載らなければ CPU は動けない。メモリのほうも重要なのだ。


posted by すz at 23:46| Comment(0) | TrackBack(0) | Jz47xx(CPU)

2010年06月07日

IPUメモ

Jz47xx には IPU (Image Process Unit) というデバイスが付いている。これでいったいどういうことができるのかについてメモ。

簡単にいうと YCrCb のようなフォーマットのイメージデータを 拡大縮小し RGB に変換して転送する装置。これがあると高速化されるのは、mplayer のような動画ソフトと jpeg のデコード。

この処理は 3 つのデータに係数をかけて加算する処理を RGB の 3つに対して行うわけでかなり重い。さらに画面サイズに合わせて拡大縮小するとなれば 相当な処理量だ。これをハードウェアで行わせることが出来るわけでかなり嬉しい機能。

    ちょっと見積もってみよう。仮に 400x226@30fps の動画があったとすると、4MB/sec で YCrCb のデータができる。これを 16bpp の フレームバッファに書くとすれば 5.3MB/sec で書き出すことになる。Jz4725B では、16 バイトの READ/WRITE には 17 メモリクロックかかる(CPUクロックなら さらにx3)。単純計算で 7.6 % のメモリ 負荷。CPU でやるとすれば .. これの数割増しぐらいのメモリ負荷になるはず。仮に 10 % だとしよう。
    あと演算がある。演算量は、multi-add が 1画素あたり 9 だとして、24M 演算 /sec 。CPU が 400MHz だとして、CPU 負荷を 10% 使えるとすると 1 演算あたり 1.6 クロック使える。... これはかなり厳しい数字。仮に 10 % でできたとしても、上記の メモリアクセスと並列にはならない。(メモリ待ちの間 CPU は止まっている) 。結局 合計 20 % ぐらい使う計算になる。
    これがバックグラウンドになればかなり嬉しいわけだ。

ところが DINUX では disable カーネルがあって わざわざ使わないようにしていたりする。

どうもメモリーの使用量が増えるというデメリットがあって 32MB しかない A320 では無視できないらしい。

mplayer や jpeg を扱うソフトだけ enable すれば良いと思うのだが そういうわけには行かないようだ。IPU は 装置なので 物理メモリを扱う。入力・出力用のイメージは物理メモリで連続した領域でないといけない。一方アプリケーションは仮想メモリで 4KB 単位の page でメモリを割り付ける。使っているうちにフラグメント化されて、物理メモリで連続した領域がなくなってしまう恐れがあるので、リザーブしているらしい。

仮想メモリを移動して 物理メモリで連続した領域を確保する機能があれば問題ないのだが、linux にあったようななかったような... あったとしても使い方が難しいなら対応が後回しにされている可能性もある。

さて、もう少し詳しく機能を調べてみよう。

まず入力フォーマット。これは Y,U,V と名前がついた 3つのプレーン。それぞれ 8bpp でパラメータには、width,height 以外に stride があり、大きなイメージの一部を入力にできる。

入力は、YUV/YCrCb フォーマットの 4:4:4, 4:2:2, 4:2:0 , 4:1:1 をサポートしている。

出力は、R8G8B8 (32bpp) か R5G6B5,R5G5B5(16bpp) こちらも width,height 以外に stride がある。

変換終了は レジスタの値で分かるが割り込みも使える。

だいたいこんなところ。画像viewer などで オリジナルを 1回展開しておけば スクロールやズーム処理を コスト 0 で出来るから、積極的に使うと良いと思うのだが ... やはりメモリが問題か。

ちなみに この機能と MXU命令 を使えばかなり動画の性能が上がる。Neo Slim 3000 では H.264(400x226,30fps) を 遅いながらも再生できた。ただし、起動の時間が異常に長く 音ずれも尋常ではなく現状では実用的ではない。

このあたりが限界なのか?というとよくわからない。根拠はないが、ソフトのチューニングとオーバクロックで この程度ならなんとかなりそうな感じはする。

ちなみに、Xburst が 2つ載っていて さらに H.264 用のアクセラレータの video Engine を載せた jz4755 は別格かも。400MHz とクロックも上がっているし、 H.264 対応とか 1080p 対応とかを謳っているが本当にまともに再生できるのかも知れない。

    データシートによると jz4755 は single core に比べて 2 倍の動画再生性能だそうだ。そしてその性能は XGA (1024x768) の H.264 の 30fps 再生。ならば jz4725や jz4740 で 720x480 の H.264 の 30 fps が出来ても不思議ではない。

    ただし 期待は 700Mhz とか噂されている jz4760 。u-boot などにはコードがマージされているのでいずれは出て来るはず。

    jz4760 は、600MHz かも知れない。プロセスが 130nm だそうだ。ある記事によると jz4750 の機能に加えて DDR2(DDR) をサポートし、USB は OTG 対応。性能は ARM11 800MHz 相当だそうだ。

    まぁ ARM勢 と比べると明らかに差を付けられている感のある jz47xx だが、いじり甲斐はある。特に MXU 命令。難解だが使いこなせると bit 操作とかいろいろ高速化できるような気がする。気が済むまで遊んでみたい。

追記:IPU の使い方

IPU が使える状態では、IPU のために 4MB の連続領域がある。

まずこの 4MB を 4 つまでのエリアに分割する。

    リクエストは、/proc/imem に対して書き込む。
    結果を知るには、/proc/imem を読み込む。

    書き込み / 読み込み フォーマットは省略。

次に バッファーを IPU に設定する。

    同じように /proc/ipu に書き込むことで設定ができる。

    ちなみに、/proc にはimem,ipu 以外に 次のようなエントリーがある。imem1 以外はデバッグ用。

    • emc
      EMC -- External Memory Controller の情報が読める。
    • pmc
      PMC -- Power Manager Module の情報が読める。
    • cgm
      write することで、CGM -- Clock Generation Module の CPCCR -- Clock Control Register に書き込みができる。
      read すると CGM の様々な設定情報が読める。
    • udc (JZ4750L, JZ4750D のみ)
      udc hotplug と書いてある。udc は デバイス側の USB 。read することで、USB の抜き差しのメッセージが見える。機能はそれだけ。
    • tlb (JZ4750 のみ)
      read しかできない。ipu の設定と TLB が見える。
    • imem1 (JZ4750D のみ)
      jz4750d は、最大 16MB の imem に加えて 最大 8MB の imem1 を確保しようとする。
      jz4750 は、最大 16MB の imem を確保しようとする。
      この 2 つは普通に 128MB ぐらいのメモリがあることが前提なのか?


ところで.. imem1 がありダブルバッファにしているのは JZ4750D のみ。これって必要なのだろうか?

    普通に考えると、IPU の転送が終わるまでは、YCrCb のメモリにアクセスできない。上記で一例として 7.5 % という数字を出したが、これはメモリを占有できたときの値。CPU や フレームバッファやその他でメモリアクセスが起きれば それだけ遅れる。30% しか利用できないとすると 25% の時間がかかる。この間、データを展開できないのは厳しいかも知れない。

    例えば、上下の 2 つに分けて 上部が終わったら 上部が使えるようになる .. みたいなことをすれば 問題ないのだが、拡大縮小をしていた場合 合わせ目が綺麗になるのかどうか?

    やはりダブルバッファに対応できたほうが良いのではないだろうか? 上記の 400x226 のデータを例にすると 必要なのは、135KB ほどだ。4MB も取るなら 割り当てられる。

    実装方法としては、imem1 を作るよりは imem の分割数を増やしたほうが良いように思う。

あと、動画しか対象として見てこなかったが、画像にも使えるのだろうか?

    JPEG の出力は、YCrCb だから やはり同じように使える。4MB をフルに使って YCrCb のデータを置いておけば 拡大縮小 や View の移動は 簡単かつ高速にできる。
    これは他の Viewer についても 同じ。
    ページという概念があって、1 ページのサイズが 1200x1600 ぐらいまでなら 4MB に収まるから、同じようなことができるはず。
    2 ページ確保してのダブルバッファというのも良いかも知れない。-- この場合 1280x1024 x 2 ぐらいまで。
posted by すz at 20:29| Comment(0) | TrackBack(0) | Jz47xx(CPU)

2010年05月19日

MXU命令メモ

Jz47xx の XBURST アーキテクチャには、MXU 命令という マルチメディア用の命令セットがある。

これが使えるのと使えないのでは、画像や動画のデコード性能が随分違うはずだと思うので、ググってみた。

どうも QI のメーリングリストの情報が 一番整理されているようだ。



どうもこれが ingenic が公開しているすべてらしく、どういう 命令があるのか 一覧すら公開されていない。

命令の 一部の名前は分かったので、それでググってみると ..


がヒットした。

dingoowiki.com の方を見ると 一覧と MXU 命令を 使うために すべきことの情報がある。

gp32x.com には、よくわからない 一覧になっているが、mxu_as (という awk スクリプト)を解析して どのように変換しているかの情報になっているらしい。

これらの情報をみても、それぞれの MXU 命令がどういう動作をするのかはっきりとは理解できない。

定義を理解するには、jz_mxu.h を見るのが一番のように思う。

jz_mxu.h には、命令に 1:1 に対応したマクロが定義されている。MXU を使う場合は、asm 命令を使用するが、MXU なしだとそれに相当する C コードにする。

これをみれば、どうやって使うのかは分かる。あとは、mxu_as 。これは、jz-crosstools-src.tar.bz2 に含まれているらしいのだが ... 66MB もある。このなかの misc/mxu_as だけを見れば良い。

とりあえず、mxu_as と jz_mxu.h を 以下に置いておく。


さて、まずは、mxu_user_guide_EN.pdfDevelopment:MXUをあわせて 見てみる。


  • 60 の SIMD 命令セットがある。(SIMD 命令は全部で 60なのはマニュアルに書いてあった)
  • xr0 - xr16 の 17 個の XMU レジスタがある。それぞれは 32bit 。
  • xr0 は、zero レジスタで 常に 0 。xr16 は コントロールレジスタ。
  • XMU 命令を使うためには xr16 の bit0 を 1 にしなくてはならない。

    • mxu-instructions-listの方は 58命令分しか解析していない。足りないのは、D16ABS , S32ABS 。

    • Jz4755 などで拡張された SIMD2 命令セットは、114 命令 (差分 54命令)だが、どうも mxu_as に拡張部分も定義されているようだ。
      jz_mxu.h には、SIMD(無印) の分しか定義されておらず、分かるのは拡張された命令の名前だけ。



ということらしい。

で? 60 個もあるという 命令はどんなものなのだろう? 

まずは、Development:MXU を見ると

  • ロード・ストア 10 種類
  • 加減算 12 種類
  • 乗算 9 種類
  • その他の算術演算 11 種類
  • シフト・シャッフル命令 16 種類

60 種類にはなっておらず 合計 58 種類が記載されている。でもよくよく見ると モードがいくつかあるようで、別々の命令として考えると種類は爆発的に増える。

それはともかく、いったいどれぐらい加速されるのだろう。あまりSIMD 命令は知らないのだが、1 命令での結果の数でカウントしてみることにする。

加減算系統だと、Q16 とか Q8 とかがあって たぶん 最大 4 つ。32bit でも D32 とかあるから 加速されるようだ。

乗算系だと D16 とか Q8 があるから 一応最大 4 つ。ただし、乗加算もあるから x2 と考えると 8つ。

1 クロックで実行できるものなのかどうか不明だが、一応 通常命令より 8 倍ぐらい高速化できるものだという風に思うことにしよう。



ところで、簡易アセンブラしかないような状況というのは分かったが、Linux での対応はどんな感じなのだろう?

見てみたのだが、どうも MXU レジスタのセーブ・リストアするようなところはないように思う。

たぶん、MXU 命令を使うプロセスを 1 つに制限しないと誤動作する。PMP だし 普通はそんな心配はいらないわけだが、うっかりするとまずいかも。

posted by すz at 23:56| Comment(0) | TrackBack(0) | Jz47xx(CPU)