2017-04-02 16 views
1

私は先月からハライドを学び始めました。 そして最後に私にとって大きな問題に遭遇しました。FuncをFuncに結合する方法はありますか?

私はHalideでCのようなコードのような関数を実装しようとしています。

for(int y = 0; y < 3; ++y){ 
    for(int x = 0; x < 3; ++x){ 
     out(x, y) = out(x-1, y-1) + 1; 
    } 
} 

ですから、最初の画像は以下の通りです。

出力画像(バウンドのうち0)

...であろう

私は2つの可能な解決策を考えました。

・解決策1

この再帰機能のように上記のアルゴリズムを定義します。

Func algorithm1(Func input, int n) 
{ 
    Func src, clamped, dst; 
    Var x, y; 

    if(n == 1){ 
      src = input; 
    }else{ 
      src = algorithm1(input, n-1); 
      src.compute_root(); 
    } 

    clamped = BoundaryConditions::constant_exterior(src, 0, 0, SIZE, 0, SIZE); 
    dst(x, y) = clamped(x-1, y-1) + 1; 

    return dst; 
} 

以下のコードのように使用してください。

Func input, output; 
input(x, y) = src(x, y); 
output = algorithm1(input, SIZE); 
output.realize(src); 

この実装はほとんど機能しません。しかし、明らかにrebundunt。 各ステージ(Func)の計算結果の大部分は、最終的な結果と一致しないため、各Funcはイメージ全体にわたって計算します。 そして、もっと大きな(通常の)画像を扱う必要があります。 私は別の解決策を考えました。

・解決策2

最初の2番目の解決策。
ある列と別の列との間の関数定義関係を宣言します。

Func algorithm2(Func src) 
{ 
    Func clamped, dst; 
    Var x; 

    clamped = BoundaryConditions::constant_exterior(src, 0, 0, SIZE); 
    dst(x) = clamped(x-1) + 1; 

    return dst; 
} 

次に、これを組み合わせてみましょう。

Func output[3]; 
output[0](x) = cast<uint32_t>(0); 
for(int i = 1; i < SIZE; ++i){ 
    output[i] = algorithm2(output[i-1]); 
} 

いいえ...問題があります。このFuncの配列をFuncとしてどのように組み合わせることができますか?

私はこの関数の配列を各関数でカラムの頭のポインタに認識させると、画像を取得できます。しかし、それを次のFuncに渡したいのですが?

最近、私はHalideのサンプル(テスト、アプリ)を見渡しました。しかし、似たような例はないと思います。 あなたは既に私の英語の不快感に気付いているかもしれませんが、実際は私は日本人です。ですから、この問題の有益な例があれば、事前に申し訳ありません。もしそうなら、それがどこにあるか教えてください。もう一つの良い実装のアイデアがあるなら、私に教えてください。とにかく私は誰かの助けが必要です!

あなたの読書に感謝します。

[編集2]

編集1は私の愚かな質問です。私はそれをスケジュールすることができますcompute_root()。 私はここにそれらを残して、本当に恥ずかしいことを決めた。 これは別の愚かな人に役立つことを願っています。

[編集1]

私は心の底からあなたの迅速かつきめ細かい対応に感謝

私は遅れて申し訳ありませんが、私のアルゴリズムを実装するために成功した後にあなたに返信したいと思います。しかし、私のハライドコードはまだやりたいことがうまくいかず、確認のためにいくつかのことがあります。

まず、私はあなたに感謝して、ハライドの誤解を実感しました。私のアルゴリズムの実装ステップの最初に、純粋なVarだけを使って定義を書きました。 エラーが発生しました。

All of a functions recursive references to itself must contain the same pure variables in the same places as on the left-hand-side. 

スケジューリングの柔軟性のためにこのエラーが発生したと考えました。このような定義が許され、分割するようにスケジュールされている場合、スケジューリング変更アルゴリズムが意味します。この理解は正しいですか?このような理解から、私はすでにチュートリアルとぼかしの例の縮小部分を読んでいますが、私はFuncの定義すべての隣のピクセルにアクセスできないと誤解しました。私はなぜか分からない。

同じ理由で縮小ドメインを分割できませんでした。私は今それを得たと思う。

あなたのコードには別の質問があります。あなたのHalideの実装例のおかげで、私はほとんど何もしたくないことを実現することに成功しました。しかし、この実装は、デバッグの容易さのために20x20の切り抜かれたイメージを処理していますが、必然的に遅いです。

私はこの遅さが還元ドメインによって引き起こされたと考えています。あなたの例では、例えば値g(10、10)を計算するとき、ハライド計算はf(0、0)からf(0、0)にスケジューリングされ、最終的に値を取得します。一方、Cの実装ではg(9,9)の値をロードしてインクリメントします。このような計算は、印刷ループネストから確認できます。

produce g: 
    for y: 
    for x: 
     produce f: 
     for y: 
      for x: 
      f(...) = ... 
     for range: 
      for range: 
      f(...) = ... 
     consume f: 
     g(...) = ... 

この再計算の回避は不可能であることを確認したいと思いますか?あなたはそれを提案しましたか?

もう1つの簡単な質問をします。このような逆依存関係がある場合、

for(int y = 2; y > 0; --y){ 
    for(int x = 2; x > 0; --x){ 
     out(x, y) = out(x+1, y+1) + 1; 
    } 
} 

ハライドはこのコードを表現できますか?

答えて

1

ここのアルゴリズム1とアルゴリズム2の部分はあまり明確ではありません。私は最初の問題の声明を理解しており、英語はうまく見えるので、あなたが求めている質問に答えるための助けとなるよう努力します。私はあなたが知らないかもしれない、またはここでの使用には明白でないいくつかのハライドメカニズムを説明することによってこれを行うでしょう。うまくいけば、これは役に立ちます。

まず第一に、さまざまな表情にハロゲン化物のFuncの次元をマッピングするために、あなたはかなりのSELECT文を使用する必要があります。

Var x, y, n; 
Func f_0, f_1, f_both; 
f_0(x, y) = ...; 
f_1(x, y) = ...; 
f_both(x, y, n) = select(n == 0, f_zero, f_one); 

これはselectに引数を追加する介して、より多くのケースに拡張することができます。これは、区分的な計算よりも再帰的な構造の方が便利ですが、タイトルの質問に対する最も直接的な答えと思われます。

第2のメカニズムはTupleです。これにより、Funcに複数の値を持たせることができます。この値は、コンパイル時定数で索引付けすることができます。私はこれがあなたが探している答えだとは思わないが、チュートリアル/ lesson_13_tuples.cppに記載されている。

最後に、Halideは、最初のコード例のケースを処理するように設計された縮小をサポートしています。これは次のようになります。

Var x, y; 
Func f, g; 
RDom range(0, 3, 0, 3); // Form is min/extent, not start/end 

f(x, y) = 0; // Initial condition 
f(range.x, range.y) = f(range.x - 1, range.y - 1) + 1; 

g(x, y) = f(x, y); 

Buffer<int32t> result = g.realize(3, 3); 

これは、最初の例の出力を生成するはずです。削減、または「更新の定義」については、チュートリアル/ lesson_09_update_definitions.cppを参照してください。

+0

長すぎるため、別の回答に返信しました。 私はあなたの返信を待っています:D – xoke

+0

私はちょうど私が最初の投稿を編集することができることを認識した。 返信は[edit1] – xoke

+0

ahhです。本当に恥ずかしいです。最後に、私はcompute_root()をスケジュールできることに気付きました。ごめんなさい。 とにかく、私はあなたの実装のアイデアのおかげでやりたいことを実現することに成功しました。どうもありがとうございました。ハライドは素晴らしいです! – xoke

関連する問題