2

このカーネルは正常に動作します:

__kernel void test(__global float* a_Direction, __global float* a_Output, const unsigned int a_Count)
{
    int index = get_global_id(0);

    if (index < a_Count)
    {
        a_Output[index * 3 + 0] = a_Direction[index * 3 + 0] * 0.5f + 0.5f;
        a_Output[index * 3 + 1] = a_Direction[index * 3 + 1] * 0.5f + 0.5f;
        a_Output[index * 3 + 2] = a_Direction[index * 3 + 2] * 0.5f + 0.5f;
    }
}

このカーネルは範囲外エラーを生成します。

__kernel void test(__global float3* a_Direction, __global float3* a_Output, const unsigned int a_Count)
{
    int index = get_global_id(0);

    if (index < a_Count)
    {
        a_Output[index].x = a_Direction[index].x * 0.5f + 0.5f;
        a_Output[index].y = a_Direction[index].y * 0.5f + 0.5f;
        a_Output[index].z = a_Direction[index].z * 0.5f + 0.5f;
    }
}

私には、どちらもまったく同じことをするべきだと思われます。しかし、何らかの理由で、2 つのうちの 1 つしか機能しません。明らかな何かが欠けていますか?

正確なエラーは次のとおりです。「GeForce GTX580M (デバイス 0) で CL_COMMAND_READ_BUFFER を実行中に CL_OUT_OF_RESOURCES エラーが発生しました。

4

2 に答える 2

2

おそらくあなたが抱えている問題は、float3 に n * 3 * sizeof(float) のバッファーを割り当てたのに、float3 のサイズとアラインメントが 12 ではなく 16 であることです。

于 2013-09-06T19:22:11.013 に答える
2

彼/彼女の答えの@arsenmと@Darkzerosは適切な説明をしましたが、少し開発するのは面白いと思います。問題は、2 番目のカーネルでこれらが発生する「隠れた」アライメントであることです。セクション 6.1.5 の標準の状態:

3 コンポーネントのベクトル データ型の場合、データ型のサイズは 4 * sizeof(component) です。これは、3 コンポーネントのベクトル データ型が 4 * sizeof(component) 境界に整列されることを意味します。

例でそれを説明しましょう:

a_Directionこれは 9 つのフロートで構成されており、これらの要素を処理するために 3 つのスレッド/ワークアイテムを使用すると仮定します。最初のカーネルでは、これらは問題ありません。スレッド 0 はインデックス 0、1、2 の要素を処理し、スレッド 1 は要素 3、4、5 を処理し、最後にスレッド 2 は要素 6、7、8 を処理します。すべて結構です。

ただし、2 番目のカーネルでは、使用するデータ構造がホスト側の観点から同じままであると仮定すると (つまり、0 から 8 までの配列)、スレッド 0 は要素 0、1、2 を処理します (また、 float3 型ベクトルは float4 型ベクトルのように動作するため、要素 4 には何もしません。2 番目のスレッド、つまりスレッド 1 は要素 3、4、5 にはアクセスしませんが、要素 4、5、6 (および何もせずに7)。

したがって、ここで問題が発生し、スレッド 2 が要素 8、9、10 (および 11) にアクセスしようとするため、境界外アクセスが発生します。

要約すると、3 要素のベクトルは 4 要素のベクトルのように動作します。

ここで、ホスト側でデータ構造を変更せずにベクトルを使用する場合は、セクション 3.12.7 で説明されているように vload3 および vstore3 関数を使用できます。標準の。そのように:

 vstore3(vload3(index, a_Direction) * 0.5f + 0.5f, index, a_Output));

ところで、次のようなステートメントを気にする必要はありません(適切な配置を前提としています):

a_Output[index].x = a_Direction[index].x * 0.5f + 0.5f;
a_Output[index].y = a_Direction[index].y * 0.5f + 0.5f;
a_Output[index].z = a_Direction[index].z * 0.5f + 0.5f;

このステートメントで十分です (要素ごとに 1 行書く必要はありません)。

a_Output[index] = a_Direction[index] * 0.5f + 0.5f;
于 2013-09-07T00:07:50.390 に答える