私は先月からハライドを学び始めました。 そして最後に私にとって大きな問題に遭遇しました。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;
}
}
ハライドはこのコードを表現できますか?
長すぎるため、別の回答に返信しました。 私はあなたの返信を待っています:D – xoke
私はちょうど私が最初の投稿を編集することができることを認識した。 返信は[edit1] – xoke
ahhです。本当に恥ずかしいです。最後に、私はcompute_root()をスケジュールできることに気付きました。ごめんなさい。 とにかく、私はあなたの実装のアイデアのおかげでやりたいことを実現することに成功しました。どうもありがとうございました。ハライドは素晴らしいです! – xoke