0

誰かが私が抱えている問題についての洞察を共有できることを願っています. 小さなプログラムは double の配列 (100000 要素) を取り、この配列のサブセットを加算して、結果を別の配列の要素に代入します。これは非常に基本的なタスクのように思えますが、私の GT630 は奇妙な動作をします。intervalLength の値が小さい場合は動作しますが (かなり遅くなります)、intervalLength が 300 前後に大きくなるとすぐに、コードは失敗します。

さらに興味深いのは、問題は加算ではなく、結果を出力配列に代入することにあるようです。以下のコードの最後の行の場合

output_dev[threadIdx.x] = totalSum;

に変更されます

output_dev[threadIdx.x] = input_dev[0];

その後、コードは非常に高速に実行されます。少なくとも 100 倍速くなり、intervalLength の値が大きくても機能します。また、行の場合

totalSum=1;

代入に先行すると、コードも高速でエラーなしで実行されます。いくつかの実験では、ループを使用するのではなく、一連のステートメントで合計を計算すると、コードも正常に機能することが示されました。

GT630 4GB を 96 個の CUDA スレッドで使用しており、1 つのブロックで 96 個のスレッドを起動しています。

コード:

extern "C" __global__ void TestCompute(double* input_dev, int input_devLen0, int* args_dev, int args_devLen0, double* output_dev, int output_devLen0)
{
    int intervalLength = args_dev[0];
    double totalSum = input_dev[num];
    if (num < input_devLen0)
    {
        for (int k = 0; k <= input_devLen0; k++)
        {
            totalSum = 0.0;
            for (int i = 0; i < intervalLength; i++)
            {
                if (input_devLen0 > i)
                {
                    totalSum += input_dev[i];
                }
            }
            if (output_devLen0 > threadIdx.x)
            {
                // totalSum = 1;
                output_dev[threadIdx.x] = totalSum; // input_dev[0];
            }
        }
    }
}
4

1 に答える 1

1

処理を小さなチャンクに分割してから、チャンクのリストをループすることで問題を解決しました。どうやら問題は、限られた数のレジスタにあります。ローエンドの GT630 カードはすぐにレジスターを使い果たしてしまうようです。これはおそらく理想的に正しい解決策ではありませんが、私の場合はうまくいきます。

于 2013-01-06T20:00:44.490 に答える