Paraisoの境界条件

直胞機械のshift命令は配列変数全体を平行移動する命令です。実際のコードが扱う配列変数は常に有限サイズですから、平行移動によりはみ出す部分の処理を境界条件により指定してやる必要があります。Paraisoは、データフローグラフの中のshift命令を解析して、境界条件を実現するのに必要な処理(袖領域など)を追加してくれます。

Paraisoでは、今のところ周期境界と自由境界という二種類の境界条件をサポートしています。
コード生成時、次元ごとにいづれかの境界条件を選ぶことができます。この二種類とほかの命令を組み合わて作れる範囲で、より複雑な境界条件も扱えます。境界条件は、Setupデータ型boundaryレコードで、Conditionを要素にもつベクトルとして指定します。

二種類の境界条件のうち、周期境界は、単に右端からはみ出したアクセスは左端のものを見るだけです。いわゆるドラクエ地図です。

これに対し、自由境界の場合は少々複雑です。まず、袖領域は、どのParaisoカーネルを1ステップ実行しても、
Setupで指定した計算したい領域、添字が0以上localSize未満の領域が埋めるのに必要十分なサイズをもって決まります。
次に、各カーネルの計算する範囲は、袖領域をふくめた最大の領域から開始し、なるべく大きな領域を埋めるように決まります。その領域の外側での値は未定義です。また、Reduce演算はつねに袖領域をふくむ全体を畳み込みます。もし袖領域を除外したい場合は手動でマスクする必要があります。

このサンプルプログラム境界条件の挙動を確かめてみましょう。このプログラムには3つのカーネルがあります。

myKernels :: [Named (Builder Vec1 Int Annotation ())]
myKernels =
  ["init" `isNameOf` do
      store table $ loadIndex (Axis 0)

  ,"increment" `isNameOf` do
      store table $ 1 + load table

  ,"calculate" `isNameOf` do
      center <- bind $ load table
      right  <- bind $ shift (Vec :~ (-1)) center
      left   <- bind $ shift (Vec :~ ( 1)) center
      ret    <- bind $ 10000 * left + 100 * center + right
      store table ret
      store total $ reduce Reduce.Sum ret
  ]

それぞれ、「配列の内容を配列添字で初期化する」「配列の内容に1を加える」「ひとつ右とひとつ左の内容を読んで値を計算する」カーネルです。

  maker.init();
  dump();
  maker.increment();
  dump();
  maker.calculate();
  dump();
  cout << "total: " << maker.total() << endl;
  cout << endl;

makeを実行すると、境界条件だけが異なる2種類のプログラムが生成されます。このように、周期境界条件のもとでは境界を飛び越えて反対側の値にアクセスできます。

$ ./main-cyclic.out
index:      0      1      2      3      4      5      6      7
value:      0      1      2      3      4      5      6      7
index:      0      1      2      3      4      5      6      7
value:      1      2      3      4      5      6      7      8
index:      0      1      2      3      4      5      6      7
value:  80102  10203  20304  30405  40506  50607  60708  70801
total: 363636

一方、自由境界のもとでは袖領域が追加され、0未満、あるいはlocalSize以上の添字の範囲にもアクセスできます。

$ ./main-open.out
index:     -1      0      1      2      3      4      5      6      7      8
value:     -1      0      1      2      3      4      5      6      7      8
index:     -1      0      1      2      3      4      5      6      7      8
value:      0      1      2      3      4      5      6      7      8      9
index:     -1      0      1      2      3      4      5      6      7      8
value:      0    102  10203  20304  30405  40506  50607  60708  70809      0
total: 283644