FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

「スターウォーズ エピソード8 最後のジェダイ」を見てきた

スターウォーズ大好きなんです。。。

starwars.disney.co.jp

本当は公開当日に行きたかったけど、忙しかったので一週間遅れ。レイトショーで見てきた。2時間30分って長いよ!

ストーリーはエピソード7ほど大きくは動かなかったような気がする。いろんな人が死んだけど。 事前情報は相変わらず何もないので、結構ドキドキハラハラしながら見ていた。 なんか旧三部作よりも、ファースト・オーダーとレジスタンスの戦力差が大きく見えて、ファースト・オーダー強すぎ!って感じがするね。

そんな中、どうやってエピソード9につなげていくのか、気になるところ。 今回はそんな、繋ぎの回って感じだった。

サントラ出たら買おうかなあ。DVDもまた買おうかな。エピソード7、ローグワン両方買っちゃったんだよね。

7th RISC-V Workshop の Vector Extension Proposal 概要

RISC-V 7th Workshopでは、Vector Extensionの説明がなされている。

https://content.riscv.org/wp-content/uploads/2017/12/Wed-1330-RISCVRogerEspasaVEXT-v4.pdf

f:id:msyksphinz:20171222012224p:plain

資料を読みながらまとめてみる。追記の可能性あり。


RISC-V Vector Extensionの特徴としては、

  • なるべくコンパクトにすること。
  • ベクトルレジスタの処理にマスクを加え、任意の要素のみ演算が適用されるようにする。
  • スカラー、ベクトル、行列の形式などをサポートする(ただし行列形式はオプションであり、ベースの仕様には追加されない)。
  • 型を混在させることが出来る。
  • (自称)これまでのベクトル命令の中で最高の出来である。

ベクトルレジスタ

ベクトルレジスタはV0からV31までの32本が定義されている。

  • 各ベクトルレジスタには"Type"とよばれるレジスタが付与される。これは16bit長のベクトルレジスタである。
  • 各ベクトルレジスタには"Type"が付けられ、ベクトルレジスタ毎に異なる"Type"を設定することが出来る。
  • "Type"はvdcfgレジスタにより設定することが出来る。16bit×32本で512bitあるのだが、これをどのように設定することが出来るのかは詳細が語られていない。
  • おそらくvdcfgレジスタが複数作られ、csrrw命令により設定されていくものと思われる。

ベクトル算術演算の実行

  • 実装されているベクトルレジスタの長さはMVLで定義する。一方で実行中の演算が適用されるベクトルの要素の長さはVLで定義する。
  • MVLの長さは全てのベクトルレジスタにおいて同一である。
  • ベクトルレジスタの長さと、演算のレイテンシは別物として考える。vadd命令を実行した場合その命令を1サイクルで実行する必要はない。何サイクル化に分けて実行して構わない。

f:id:msyksphinz:20171221011520p:plain

  • 4サイクルで実行する場合

f:id:msyksphinz:20171221011615p:plain

  • 2サイクルで実行する場合

f:id:msyksphinz:20171221011634p:plain

マスク付きの実行

ベクトル命令は、マスクを使ってエレメント毎に演算の有効無効を指定できる。例えば、vadd v5, v3, v4, v1.tとする場合、以下のようにv1.tで指定されるレジスタの値に依存してマスクがかけられる。

f:id:msyksphinz:20171221012156p:plain

メモリアクセス

ロード命令・ストライド付きロード命令

ロード命令は非常にシンプルなロード命令。Unalignedも許可するが、非常に低速なことが前提。

ストライド付きロード命令は、いわゆるGather命令。RISC-Vの仕様であるGather命令はさらにえげつない。 f:id:msyksphinz:20171221013344p:plain

Gather命令

Gather命令は、各ベクトルエレメントで、ロードするメモリアドレスのオフセットを自由に設定できる。 結構実装が大変になる気がするが。。。

f:id:msyksphinz:20171221014131p:plain

ベクトルレジスタの型、型変換

  • 異なる"Type"が設定されたレジスタ同士の演算でも、ある程度ルールの中ならば演算を適用させることが出来る。
vcvt v1(F32) --> v0(F16)
vcvt v1(u8) --> v0(F32)
vcvct v1(F32) --> v0(I32)

この場合のベクトルレジスタのサイズが非常にややこしいことになる。 各ベクトルレジスタは異なる型を持つことが出来るが、MVL(ベクトルレジスタ当たりのエレメントの数)は常に同一である。 したがって、以下のようなことが出来るようになる。

  • プログラムコードが2つのF16ベクトルレジスタおよび2つのF32ベクトルレジスタを必要としている場合、
    • F16(=2byte)×2 + F32(=4byte)×2 = 12byteが必要となる。

このとき、ベクトルレジスタのハードウェアとしては  4\text{byte}\times 4\text{element}\times 32\text{本}=512\text{byte} 保持しているとすると、 \text{MVL}=512\text{byte} / (12\text{byte} + 4\text{byte(使用しないレジスタ)}) = 32となり、1ベクトルレジスタ当たり32エレメントを持つことが出来るようになる。

これをどのようにベクトルレジスタに当てはめるかは実装に任されている。例えば、以下のような構成が可能となる。

上位の 4\text{byte}\times 4\text{element}\times 4\text{本}\times 2\text{レジスタ}(=128\text{byte}) をF16のベクトルレジスタとして使い、 次の4\text{byte}\times 4\text{element}\times 8\text{本}\times 2\text{レジスタ}(=256\text{byte}) をF32のベクトルレジスタとして使う。

f:id:msyksphinz:20171222012123p:plain

以上のように、ベクトルレジスタのハードウェアを実際のアーキテクチャ的などのレジスタに割り当てるかは非常に柔軟に持つことが出来るようになる。 その分、かなり制限を加えないと実装が大変そうだが... (検証も大変そうだ)。

と思ったら、命令コード表には入っていた。師匠に指摘していただきました。ありがとうございます。

f:id:msyksphinz:20171226010836p:plain

RISC-VのCompression命令仕様の理解とISSの実装

RISC-Vのハードウェア仕様の中で、RV64GCとか、RV32IMACとか出てくるが、その中で"C"というのは"Compressed"命令ということで、命令長が16bitの短縮命令のことを指す。

サポートしているアーキテクチャの中で"C"が入っていれば、このCompressed 命令を動かすことが出来るということで、命令コードサイズの短縮につながる。 ARMのThumb命令、MIPSのMIPS16eに近いものだ。

似て非なる"C"命令と"E"命令

時々混乱するのだが、Compressed命令群と雰囲気が似ている命令で"E"命令群が存在する。これはRV32Eと呼ばれ、RV32I(32bit整数命令)のハードウェア的な縮退版を指す。

主な変更点としては、RV32Iでは32本ある整数レジスタを16本に減らしている。使用できる命令自体はRV32Iと同一で、ただしx16-x31までの搭載していない汎用レジスタにアクセスすると例外を発生させる。 また、カウンタレジスタ(rdcycle[h],rdtime[h], rdinstret[h])は無理に実装しなくても良いという制限がある。

というわけでRV32Eは、命令長自体を短縮させるわけではなく、ハードウェア量を減らすための実装なので、そこは注意。

Compressed命令の概要

まず命令フォーマットとして、16bit長命令であることを示すのに、下位の2bitを使う。下位の2bitが2'b11であれば、32ビット長命令以上になるが、それ以外では16bit長命令となる。 非常にリッチである。

f:id:msyksphinz:20171220020108p:plain
(RISC-V User Instruction Manulより引用)

注意すべきは、RISC-Vのサポートしているモードによって実行される命令の意味が異なるということだ。例えば、RV32/RV64ではC.FLDであり、RV128ではC.LQ として解釈されて実行される。

命令フォーマットは以下に示すようになっている。レジスタ本数は基本モードと同様に32本利用できるが、32本をフルにアクセスできるのはCR(レジスタ間演算)、CI(レジスタ、即値)、CSS(スタック操作命令)のみとなる。

f:id:msyksphinz:20171220020226p:plain

それ以外の命令は、以下の表に従ってアクセスできるレジスタが制限される。 ロードストアに関しても同様だが、スタック相対のアクセスの場合のみ、CSS(Stack-relative Store)により専用命令が用意されている。この場合は任意のレジスタのデータをスタックに積むことが出来る。

f:id:msyksphinz:20171220020347p:plain

大きく分けてCompressed命令の仕様は以下のように分類される。

  • CR : レジスタ間演算命令。2オペランドを取り、1オペランドを上書きする形の命令が用意されている。
  • CI : レジスタ、即値演算命令。即値とレジスタの演算、または即値を代入する演算。
  • CSS : スタック相対メモリアクセス命令。スタックポインタをベースとしてメモリアクセスを行う。ロードとストアがあり、整数レジスタ用と浮動小数レジスタ用が用意されている。
  • CIW : 即値が広くとることが出来るレジスタアクセス命令。スタックポインタの更新などに使用される。
  • CL : ロード命令。
  • CS : ストア命令。
  • CB : 分岐命令。レジスタ比較を行うが、比較対象のレジスタはゼロレジスタに限定される。PC相対分岐を行う。
  • CJ : ジャンプ命令。PC相対ジャンプを行う。JumpとJump And Linkが用意されている。

RISC-V の命令セットシミュレータへのCompressed 命令実装の検討

自作命令セットシミュレータにRISC-Vを実装する検討をしているのだが、いくつか問題があった。まず、命令のモード毎に有効な命令が異なるということだ。 たとえば、下記の命令リストにおいて、C.FLWC.LDは命令コード的に全く同じなので、RISC-Vのサポートしている命令形態によって意味が異なる。

f:id:msyksphinz:20180603234957p:plain

したがって、とりあえずは命令デコードテーブルは重複している命令の片方を無効化して生成を行った。

  • 自作RISC-Vシミュレータの命令デコードテーブルの一部
$arch_table.push(Array['c.addi4spn', 16, 'XXXXX', 'XX',     'XXXXX', 'XXXX0', '00X', 'XXXXX', 'XXXXX00', 'COMPRESS', "", ""])
$arch_table.push(Array['c.fld     ', 16, 'XXXXX', 'XX',     'XXXXX', 'XXXX0', '01X', 'XXXXX', 'XXXXX00', 'COMPRESS', "", ""])
# $arch_table.push(Array['c.lq      ', 16, 'XXXXX', 'XX',     'XXXXX', 'XXXX0', '01X', 'XXXXX', 'XXXXX00', 'COMPRESS', "", ""])   # RV128
$arch_table.push(Array['c.lw      ', 16, 'XXXXX', 'XX',     'XXXXX', 'XXXX0', '10X', 'XXXXX', 'XXXXX00', 'COMPRESS', "", ""])
$arch_table.push(Array['c.flw     ', 16, 'XXXXX', 'XX',     'XXXXX', 'XXXX0', '11X', 'XXXXX', 'XXXXX00', 'COMPRESS', "", ""])
# $arch_table.push(Array['c.ld      ', 16, 'XXXXX', 'XX',     'XXXXX', 'XXXX0', '11X', 'XXXXX', 'XXXXX00', 'COMPRESS', "", ""])   # RV64/RV128
$arch_table.push(Array['c.fsd     ', 16, 'XXXXX', 'XX',     'XXXXX', 'XXXX1', '01X', 'XXXXX', 'XXXXX00', 'COMPRESS', "", ""])
# $arch_table.push(Array['c.sq      ', 16, 'XXXXX', 'XX',     'XXXXX', 'XXXX1', '01X', 'XXXXX', 'XXXXX00', 'COMPRESS', "", ""])
$arch_table.push(Array['c.sw      ', 16, 'XXXXX', 'XX',     'XXXXX', 'XXXX1', '10X', 'XXXXX', 'XXXXX00', 'COMPRESS', "", ""])
$arch_table.push(Array['c.fsw     ', 16, 'XXXXX', 'XX',     'XXXXX', 'XXXX1', '11X', 'XXXXX', 'XXXXX00', 'COMPRESS', "", ""])
# $arch_table.push(Array['c.sd      ', 16, 'XXXXX', 'XX',     'XXXXX', 'XXXX1', '11X', 'XXXXX', 'XXXXX00', 'COMPRESS', "", ""])   # RV64/RV128
  • Compressed命令のテストパタンの解析

Compressed命令のテストパタンを流してみると、どうも4-byteアラインではなく2-byteアラインに命令が配置されていてもジャンプできなければならないらしい!?

RISC-Vの例外仕様では、Instruction Address Misaligned例外は4-byteにアラインされていないことが条件かと思っていたけど、RVCに関してはそうではないらしい。

RISC-Vのメーリングリストを探していると見つけた。

An instruction address misaligned exception is generated on a taken branch or unconditional jump if the target address is not four-byte aligned. No instruction fetch misaligned exception is generated for a conditional branch that is not taken.

with a commentary note:

Instruction fetch misaligned exceptions are not possible on
machines that support extensions with 16-bit-aligned
instructions, such as the compressed instruction set extension,
C.

なるほどー、つまりCompressed命令をサポートしている実装では、Instruction Fetch Misaligned 例外は発生しないということか。これはびっくり。

というわけで例外的に命令フェッチアライン例外を無効にして自作ISSでRVC命令を流すようにすると、とりあえずデコードは出来たようだ。

f:id:msyksphinz:20180605001433p:plain

あとは中身の実装をしていかなければ。

RISC-Vオープンソースコア Rocket-Chip, BOOMv1, BOOMv2 のサイクル性能比較

RISC-V Day Tokyo 2017お疲れさまでした。 私は午前中から適当なことを喋って、特にお金をもらっているわけでもないのにRISC-V Foundationとか、SiFiveのIPについてべた褒めをしてしまったのだった。

あとで何人かには聞かれたのだが、講演で使った資料にはバックアップスライドがあって、各種オープンソースコアのサイクル数ベンチマークを取った資料がある。 これは独自に取得したベンチマーク結果で、その正しさは未知数なのだが、参考までに公開してみよう。

比較したのは、

使用したのはriscv-testsのbenchmarksテストセットで、ログに表示される命令数とサイクル数を取得して一覧にしている。

Inst-Count Rocket-Cycle Inst-Count(BOOM) BOOM v1-Cycle BOOM v2-Cycle
dhrystone.riscv 198654 250623 200129 200129 154647
median.riscv 4159 5758 4259 7637 9956
mm.riscv 25199 29396 25287 17482 17044
mt-matmul - 42520 - 15948 16295
mt-vvadd.riscv - 23836 - 8846 7049
mt-vvadd.riscv - 21482 - 7637 6049
multiply.riscv 24298 28567 21003 18371 20044
qsort.riscv 125723 204247 124233 205474 254778
rsort.riscv 173305 227307 171284 112700 101057
spmv.riscv 33924 59877 32535 27991 28583
towers.riscv 6170 6338 6623 4607 5415
vvadd.riscv 2420 2496 2519 2040 2014

グラフにしてみるとこんな感じ。Rocket-Chipを1.0にして、そのサイクル数の比率を測定している。縦軸が大きいほど性能が良い。

f:id:msyksphinz:20171219232449p:plain

BOOMはRocket-Chipに比べて、それなりに性能が出ている。ただし、BOOMv1はBOOMv2よりもサイクル性能が良さそうな気がする。

vaddのような単純なパタンではBOOMは性能が出ているが、これはBOOMが、faddの単純ループのレイテンシを隠蔽できるからであり、それ以外ではそこまで大きな差が現れる訳ではない。

  • riscv-tests/benchmarks/mt-vvadd/vvadd.c
//--------------------------------------------------------------------------
// vvadd function

void __attribute__((noinline)) vvadd(int coreid, int ncores, size_t n, const data_t* x, const data_t* y, data_t* z)
{
   size_t i;

   // interleave accesses
   for (i = coreid; i < n; i+=ncores)
   {
      z[i] = x[i] + y[i];
   }
}

ただし、qsortとmedianでは、BOOMv2はBOOMv1よりも遅いどころか、Rocket-Chipよりも遅いんだよなあ。このへんはアプリケーションの特性によるかもしれない。

Computer Architecture 6th Editionの7章"Domain-Specific Architecture" を読む (7.3章の用語集)

ヘネパタ第6版こと、"Computer Architecture 6th Edition" では、第7章でドメイン固有アーキテクチャの章が新設された。 これを機会に、しっかり読んでいこう。

Computer Architecture, Sixth Edition: A Quantitative Approach (The Morgan Kaufmann Series in Computer Architecture and Design)

Computer Architecture, Sixth Edition: A Quantitative Approach (The Morgan Kaufmann Series in Computer Architecture and Design)

7.3章はがっつりディープニューラルネットワークの内容だ。用語集も入っている。これを機にしっかり勉強しよう。

目次

これは著者が読んだ内容をまとめているだけなので、誤訳、理解不足により誤っている可能性があります!鵜呑みにしないようにお願いします。


  • 一般用語
用語 略語 簡単な説明
Domain-specific architectures DSA 特定のドメイン用に設計された専用プロセッサ。ドメイン外の処理は、他のプロセッサにより処理されることが期待されている。
Intellectual property block IP SOCにインテグレートすることのできるポータブルデザインブロック。
System on a chip SOC コンピュータのすべてのコンポーネントを含んだチップ; PMDなどで使われる。
用語 略語 簡単な説明
Activation - 人工ニューロンが「活性化」した結果; 非線形関数の出力である。
Batch - フェッチ処理の負荷を減らすために、一緒に処理するデータセットのまとまり。
Convolutional neural network CNN 前のレイヤからの出力の、空間的に近くの領域の非線形関数の集合を入力として受け取り、それに重みを乗算するDNN。
Deep neural network DNN 人工ニューロンを多数レイヤとして並べたもの。各レイヤは、前段のレイヤからの出力に、重みを掛け合わせて非線形関数を適用する。
Inference - DNNの生産フェーズ、Prediction(推論)とも呼ばれる。
Long short-term memory LSTM 時系列の分類、処理、推論に適しているRNN。これは「セル:cells」と呼ばれるモジュールの階層構造により構成されている。
MultiLayer perceptron MLP 前のレイヤで、重みを掛け合わせた結果に対して非線形関数出力を適用したものを入力とするDNNのことを示す。これらのレイヤは全て結合されている。
Rectified Linear Unit ReLU f(x)=max(x,0)で表現される非線形関数。有名な他の非線形関数としては、Sigmoid関数やHyperbolic Tangent(tanh)関数などがある。
Recurrent neural network RNN 入力が、前のレイヤの出力と、前の状態であるDNNのこと。
Training - DNNの学習フェーズ。学習(learning)とも呼ばれる。
Weights - Trainingフェーズ中に学習される値; パラメータ(parameter)とも呼ばれる。
  • TPU用語
用語 略語 簡単な説明
Accumulators - 4096個の256×32-bit(=4MB)のレジスタ群で、MMUの出力を格納し、Activation Unitの入力値として使用する。
Activation Unit - 非線形関数(ReLU, sigmod, hyperbolic tangent, max pool, average pool)として動作する。Accumulatorから入力を受け取り、Unified Bufferに計算結果を出力する。
Matrix multiply Unit MMU 256×256個のシストリックアレイ状の8-bit算術演算ユニットで、積和演算を実行する。演算器の入力はWeight MemoryおよびUnified Bufferで、出力はAccumulatorに格納される。
Systoric Array - 処理ユニットのアレイで、近傍のデータを上位から受け取り、部分計算結果を計算し、同じ入力値とその計算結果を次の近傍の演算器に渡す。
Unified Buffer UB 25MBのオンチップメモリで、Activationを保持する。DNNの実行時には、Activationの結果をDRAMにすピルアウトしないようにサイズを調整する。
Weight memory - 8MBの外部DRAMチップで、MMUに渡す重み情報を保持する。重み情報はMMUに渡される前にWeight FIFOに転送される。

Computer Architecture 6th Editionの7章"Domain-Specific Architecture" を読む (7.1, 7.2章)

ヘネパタ第6版こと、"Computer Architecture 6th Edition" では、第7章でドメイン固有アーキテクチャの章が新設された。 これを機会に、しっかり読んでいこう。

Computer Architecture, Sixth Edition: A Quantitative Approach (The Morgan Kaufmann Series in Computer Architecture and Design)

Computer Architecture, Sixth Edition: A Quantitative Approach (The Morgan Kaufmann Series in Computer Architecture and Design)

目次

これは著者が読んだ内容をまとめているだけなので、誤訳、理解不足により誤っている可能性があります!鵜呑みにしないようにお願いします。


7.1 イントロダクション

ゴードン・ムーアの提唱した半導体プロセスの法則について、彼自身はまたその終焉についても言及している。 その証拠に、彼の創業したインテルでも、半導体プロセスの開発の速度は鈍化し始めている。

本書のこれまでの章で紹介したように、半導体プロセスの進化によって、1980年には5ステージの単純なパイプラインにより25,000個のトランジスタでのみ構成されたプロセッサは、現在は100,000個のトランジスタにより、汎用的なコードを汎用プロセッサで高速に動作させるようなメカニズムが搭載されるようになってきている。 - 1次キャッシュ、2次キャッシュ、3次キャッシュ、4次キャッシュ - 512bit 浮動小数SIMDユニット - 15ステージ超のパイプライン - 分岐予測 - アウトオブオーダ実行 - 投機プリフェッチ - マルチスレッディング - マルチプロセッシング

これらの洗練されたアーキテクチャは、C++のような効率的な言語で書かれた数百万行のプログラムで威力を発揮することをターゲットにしているが、アーキテクトはこれらのコード自身はブラックボックスとして扱い、このコードが実際にはどのようなプログラムであるのかについては関知しない。 SPEC2017のようなベンチマークプログラムは、CPUの性能を測定するために人工的に作られたプログラムである。 コンパイラの開発者はハードウェアとソフトウェアの橋渡しを行う人々ではあるが、彼らはアプリケーションの高位な動作についての知識は限定的なものである。 これにより、コンパイラC/C++GPUアーキテクチャの部分で、文法的な橋渡しを行うことが出来無くなってしまう。

第1章で説明したように、でなーどスケーリングはムーアの法則が終焉するよりも前に終わっている。 これにより、より多くの取らんじ沙汰がスイッチングすることにより、より多くの電力が消費されるようになり、シングルコアの性能を向上させるよりも、マルチコアで処理を分散させる方向に進んでいる。 汎用プロセッサのコストパフォーマンス電力効率を向上させるためには、私たちは他に手の打ちようがないのである。 なぜならば、使うことの出来る電力は限られており(エレクトロマイグレーションや、チップの構造や温度の限界による)、これ以上高い性能(1秒間あたりの演算量)を向上させるためには、演算当たりの消費電力を下げる必要がある。

図7.2は、第1章で示したメモリと論理のエネルギーコストの相対値を示したものである。 このオーバヘッドでは、既存のコアを多少改造することにより10%の電力効率向上を行うことが出来るかもしれないが、プログラマビリティを維持しながら桁違いのエネルギー効率改善を行うためには、コアの演算器の数を1から数百に増やす必要がある。 このレベルの効率向上を行うためには、汎用コアから"ドメイン固有アーキテクチャ(Domain Specific Architecture: DSA)"に抜本的な変更を行う必要がある。

したがって、かつてシングルコアからマルチコアに映ったように、汎用プロセッサとDSAでチップを構成するという動きに代わってきている。 汎用プロセッサは、オペレーティングシステムのような巨大なプログラムを動作させて、DSAは実行できるタスクの領域は小さいが、非常に高速かつ効率的に動作することが出来る。 このようなコンピュータは、かつてのホモジニアスのマルチコアというよりも、ヘテロジニアスなコンピュータであるということが出来る。

これまでの数十年は、ムーアの法則に従ってアーキテクチャを増強させてきた(キャッシュ、アウトオブオーダ実行、など)。 これらの構造は、アルト固有のアプリケーションの分野では活用できない場合が多い。 例えば、キャッシュは汎用プロセッサにおいては非常に有用であるが、DSAで実行する、アプリケーションのメモリアクセスパタンが予測やすいようなものや、巨大なデータを使用しており、キャッシュがほとんどヒットしないような場合には有益ではない。 従って、DSAは特定のアプリケーションにおいてシリコンの使用効率を向上させ、エネルギー効率を向上させることが出来る。

アーキテクトは、SPEC2017のような巨大なC++のアプリケーションを全てDSAで実行しようとはおまわないだろう。 ドメイン固有アルゴリズムは、ほとんどの場合大きなシステムの中の、計算が中心になる小さなカーネルの部分に焦点があてられる。 たとえば、物体認識や音声認識などである。 DSAはプログラム全体を実行するわけではなく、そのプログラムの一部に焦点を当てる。 さらには、ベンチマークプログラムのソースコードを書き換えるのは特に問題ない行為である。 したがって、DSAに興味を持ったアーキテクトはアプリケーションのドメインアルゴリズムについても興味を持つ必要がある。

さらに、専門の領域を拡大させるだけでなく、ドメイン固有アーキテクチャのアーキテクトは、ターゲットとして十分にSOCのシリコンを使う価値があるかどうかを考える必要がある。 カスタムチップにおける「開発費負担(nonrecurring engineering: NRE)」は、チップの設計費用とカスタムチップのソフトウェアの開発費が含まれる。 例えば、1000チップ程度しか出回らないようであれば、それは価値がなくなってしまう。

少量のチップしか出回らないアプリケーション領域で、DSAを使用するための一つの方法としては、FPGAのような再構成可能なチップを使うということである。 再構成可能なチップのNREは、カスタムチップのNREよりも低く、同じチップを用いていくつかの異なるアプリケーションを実行することが出来るようになる。 しかし、ハードウェアの効率はカスタムチップよりも高くはないため、FPGAによって得られる利益は限定的である。

もう一つのDSAの挑戦は、ソフトウェアの移植である。 C++プログラミング言語のような、慣れ親しんだソフトウェアの開発環境とコンパイラを提供することは容易ではない。

以降では、DSAの設計のための5つのガイドラインについて紹介し、例としてディープニューラルネットワーク(Deep Neural Network:DNN)について紹介する。 DNNは現在のコンピュータ業界の様々な領域において革命的であるため、例として選んだ。 いくつかのハードウェアターゲットと異なり、DNN固有のアーキテクチャは、多くの問題に適用可能である。 従ってDNN固有アーキテクチャを、音声認識、画像認識、言語認識、翻訳、サーチランキングなどの様々な幅広い領域に適用可能である。

私たちは、4つのDSAの例について見ていく。 データセンタにおける、DNNを高速化させるための2つのカスタムチップと、多くのドメインにおいて高速化を行うためのFPGAに搭載したDNN、さらに情報端末(Personal Mobile Device: PMD)用に、画像処理を行うためのチップについて紹介する。 DSAのコストパフォーマンスについて、DNNのベンチマークを用いてCPUとGPUと比較する。

7.2 DSAのガイドライン

ここでは、7.4章から7.7章までで見ていく、DSAデザインの一般的なガイドラインについて見ていく。 これらの5つのガイドラインは、面積効率やエネルギー効率の向上を導くだけでなく、以下の2つのメリットももたらす。 まず、デザインをシンプルにし、DSAのNREを削減する。 次に、7.9章でみるように、これらの原則に従うDSAアクセラレータは、従来のプロセッサのような性能最適化のような最適化よりも、ユーザアプリケーションのような応答時間のデッドラインを守るようなアプリケーションに適している。

  1. データの移動距離を最小化するために、専用メモリを使用せよ。 マイクロプロセッサの複数レベルのキャッシュは優れたものだが、固有のアプリケーションにおける特定の関数内でのデータの移動は、ソフトウェアにより制御されたメモリによって実現することが出来る。

  2. 高度なマイクロアーキテクチャ最適化されたリソースを、より多くの演算器とメモリに使用する 7.1章説明七曜に、ムーアの法則によりCPUとGPUは資源を集中させる最適化(アウトオブオーダ実行、マルチスレッディング、マルチプロセッシング、ぷりふぇっチング、アドレス結合など)を行ってきた。 しかし、範囲の狭い固有ドメインでは、これらの資源は、より多くのプロセッシングユニットもしくはオンチップメモリに使用した方が適切である。

  3. ドメインにマッチする並列性の形を使用せよ DSAのターゲットのドメインは、常に本来並列性を持っている。これを活用する。 たとえば、データレベルの並列性を持っているアプリケーションならば、MIMD演算を使用するよりもSIMD演算を活用することが出来る。 そのドメインで命令セットの並列性があるならば、VLIWを活用することが出来る。

  4. データサイズを削減し、そのドメインで必要な型に限定する

多くのドメインのアプリケーションでは、典型的にメモリアクセス性能に律速される。したがって、小さいデータ型を使うことにより、メモリ帯域とオンチップメモリの使用効率を向上させることが出来る。

  1. コードをDSAに移植するためにドメイン固有のプログラミング言語を使用せよ

ドメイン固有のプログラミング言語は、アーキテクトがDSAに注目する前から有名になり始めている。 たとえば、画像処理のためのHalideやDNNのためのTensorFlowなどである。 これらの言語はアプリケーションをDSAに移植しやすくする。

ガイドライン TPU Catapult Crest Pixel Visual Core
デザインターゲット データセンタ ASIC データセンタ FPGA データセンタ ASIC PMD ASIC/SOC IP
1. 専用メモリ 24MB ユニファイドバッファ 4MB アクセラレータ 構成変更可能 N.A. コアあたり: 128kB ライン バッファ: 64KB P.E. Memory
2. 多くの演算ユニット 65,536 積和演算器 構成変更可能 N.A. コアあたり: 256積和演算器 (512ALU)
3. 並列性 シングルスレッド、SIMD、 インオーダ SIMD, MIMD N.A. MPMD, SIMD, VLIW
4. データサイズ削減 8-bit, 16-bit 整数 8-bit, 16-bit整数 32-bit 浮動小数 21-bit浮動小数 8-bit, 16-bit, 32-bit整数
5. ドメイン固有言語 TensorFlow Verilog TensorFlow Halide/TensorFlow

PowerPointで複雑な図形を作成するときに使える「図形の結合」

最近知ったPowerPointの技。 PowerPointの図形はデフォルトで用意された四角形や三角形などを使うことが出来るが、ではそれ以外の複雑な形を作るためにはどのようにすればよいのか?

例えば、我々コンピュータアーキテクチャの世界では"ALU"(通称パンツ)をPowerPointで書かなければならないことがある。 この場合、いくつかの手段があるが、有名なのは、「フリーフォーム」を使うこと。これで図形を書いて、1つのオブジェクトとする方法がある。

f:id:msyksphinz:20171216214759p:plain

ただし、この方法は各プロットの水平を維持したり、水平垂直、左右対称などの調整が難しい。 もう少し楽な方法で、基本のブロックを組み合わせて複雑なブロックを作ることはできないだろうか。

「図形の結合」で複雑な図形を作る

ここで使えるのが、「図形の結合」だ。「書式」タブの気づきにくいところにシレッと配置されている。

f:id:msyksphinz:20171216215251p:plain

これを使うと、複数のブロックの結合、論理結合を行うことが出来る。2つのブロックを選択して、「図形の結合」のボタンから実行したい論理結合を選択するだけだ。

これにより、ブロックを重ねただけだと効果が重なってしまうのだが、結合させると効果もうまく適用させることが出来る。

f:id:msyksphinz:20171216215655p:plain

「図形の結合」を使って、ALUを作る

これを使えば、我々アーキテクトが必要なALUブロックを簡単に作ることが出来る。「図形の結合」から「型抜き」を選択する。

f:id:msyksphinz:20171216220056p:plain

複雑な形は、基本ブロックを作って、論理結合をすることで作るのが簡単そうだ。