2

しばらくの間、OpenCL カーネルを使用して、マーチング キューブ アルゴリズムを CPU から GPU に移行しようとしています。

私が得ている問題は、カーネル内の関数が奇妙な値を返すことです。そのため、float3 コンポーネントが 0、0.5、および 1 である 12 個の float3 の配列で可能な戻り値を指定するテスト ケースを作成しました (以下のコードを参照)。 )

何らかの理由で奇妙に大きな数値が得られます。たとえば、「11」の edgeIndex は float3: (-145085952., 6.600e-43#DEN, 0) を返しますが、(1, 0, 0.5) である必要があります。私が知る限り、y座標は基本的に0なので問題はありませんが、x座標は頭痛の種です。

最初は、OpenCL が指定された値を float3 に変換する際に問題があるのではないかと考えたので、".f" で指定しました (例: (float3)(0.f, 0.5f, 0.f))。これは、どこかで間違いを犯さなければならないと私に思わせる、さらに奇妙で異なる結果をもたらすだけでした. 私はOpenCLにかなり慣れていません(これはそれを使用した最初の実際のプロジェクトです)、一般的にそれほど長くプログラミングを行っていないので、ここで初心者の間違いを犯していないことを願っていますが、これと関連する問題に取り組もうとしました何日もの間、解決策が見つかりません。

可能な限り問題を絞り込み、コードが実行する各ステップでコードが本来の動作をしているかどうかをテストしました。「CalculateEdgePos」の関数呼び出しまではすべてうまくいっているようで、期待どおりの結果が得られます。不要なコードの機能をすべて取り除きました (したがって、「values」パラメーターは現在使用されていないため無視してかまいません) が、今は頭がいっぱいです。

奇妙な結果を返す関数:

float3 CalculateEdgePos(int edgeIndex, __global int* values) 
{ 
    if(edgeIndex == -1) 
    { 
        return (float3)(-1,-1,-1); 
    } 

        float3 EdgePositions[12] = {(float3)(0, 0.5, 0), (float3)(0.5, 1, 0), (float3)(1, 0.5, 0), (float3)(0.5, 0, 0), (float3)(0, 0.5, 1), (float3)(0.5, 1, 1), (float3)(1, 0.5, 1), (float3)(0.5, 0, 1), (float3)(0, 0, 0.5), (float3)(0, 1, 0.5), (float3)(1, 1, 0.5), (float3)(1, 0, 0.5)};

        return EdgePositions[edgeIndex];
} 


and the part of the kernel with the function call and the result getting send back to the CPU 
(edgeIndex is calculated fine beforehand):

__kernel void MarchCubes(__global float* outVertices, __global int* values, __global int* edges) 
{ 
.
.
.
    float3 vertexPos = CalculateEdgePos(edgeIndex, values); 
    float coords[3] = {vertexPos.x, vertexPos.y, vertexPos.z}; 

    outVertices[get_global_id(0)] = coords[coordIndex]; 
}

あなたの誰かが提供するヒントや助けを持っているなら、私はそれを大いに感謝します. これ以上のコード スニペットが必要な場合はお知らせください。ただし、奇妙な動作をするのは指定された関数だけなので、これで十分だと思います。

よろしく、foodius

4

1 に答える 1

1

もちろん、私が長い間座っていたこの問題を投稿した直後に、解決策を見つけました...

したがって、誰かが同様の問題を抱えている場合:

配列自体の宣言で配列要素を正しく宣言すると、OpenCL は本当に気に入らないようです。したがって、書く代わりに:

 float3 EdgePositions[12] = {(float3)(0, 0.5, 0), (float3)(0.5, 1, 0), (float3)(1, 0.5, 0), (float3)(0.5, 0, 0), (float3)(0, 0.5, 1), (float3)(0.5, 1, 1), (float3)(1, 0.5, 1), (float3)(0.5, 0, 1), (float3)(0, 0, 0.5), (float3)(0, 1, 0.5), (float3)(1, 1, 0.5), (float3)(1, 0, 0.5)};

私は今書いた:

float3 pos0 = (float3)(0.f, 0.5f, 0.f);
    float3 pos1 = (float3)(0.5f, 1.f, 0.f);
    float3 pos2 = (float3)(1.f, 0.5f, 0.f);
    float3 pos3 = (float3)(0.5f, 0.f, 0.f);
    float3 pos4 = (float3)(0.f, 0.5f, 1.f);
    float3 pos5 = (float3)(0.5f, 1.f, 1.f);
    float3 pos6 = (float3)(1.f, 0.5f, 1.f);
    float3 pos7 = (float3)(0.5f, 0.f, 1.f);
    float3 pos8 = (float3)(0.f, 0.f, 0.5f);
    float3 pos9 = (float3)(0.f, 1.f, 0.5f);
    float3 pos10 = (float3)(1.f, 1.f, 0.5f);
    float3 pos11 = (float3)(1.f, 0.f, 0.5f);

    float3 EdgePositions[12] = {pos0, pos1, pos2, pos3, pos4, pos5, pos6, pos7, pos8, pos9, pos10, pos11};

そして今では魅力のように機能します。

なぜこれが許可されないのか、または偽の値を返すのか、私にはまだよくわかりません。

于 2019-10-09T12:18:50.403 に答える