1

问题:

我正在尝试使用我的显卡使用 cudafy.net 进行一些计算。我现在运行了我的内核的 2 个版本,并且我在特定的时间间隔内不断收到错误,即数组中的每个第二个位置都是 0.0,但应该更大。下表列出了 GPU 返回的值与正确值的对比。注意:我读过比较浮点数并不理想,但是当我应该得到 6.34419e17 这样大的东西时得到 0.0 似乎是错误的。

I              GPU    Correct Value

16,777,217     0.0    6.34419E17
16,777,219     0.0    6.34419E17
...            ...    .....

通过快速扫描它们,它们似乎出现在每 2nd i 值处。

到目前为止检查:

我还以不同的起始值运行了以下代码,因为我认为这可能是数据的问题,但对于每个错误,我仍然得到相同的 i 值。

我还更改了将内存分配到 GPU 上的顺序,但这似乎并不影响结果。注意:由于我在 VS 中调试,所以在我停止后我没有明确清除 GPU 上的内存。一旦我停止调试,这会被清除吗?一旦我重新启动我的电脑,错误仍然存​​在。

显卡:

我的显卡如下:EVGA GTX 660 SC。

代码:

我的内核:(注意:我有几个变量在下面没有使用,但我没有删除,因为我想一次删除 1 个东西以确定导致此错误的原因)

    [Cudafy]
    public static void WorkerKernelOnGPU(GThread thread, float[] value1, float[] value2, float[] value3, float[] dateTime, float[,] output)
    {
        float threadIndex = thread.threadIdx.x;
        float blockIndex = thread.blockIdx.x;
        float threadsPerBlock = thread.blockDim.x;
        int tickPosition = (int)(threadIndex + (blockIndex * threadsPerBlock));

        //Check to ensure threads dont go out of range.
        if (tickPosition < dateTime.Length)
        {
            output[tickPosition, 0] = dateTime[tickPosition];
            output[tickPosition, 1] = -1;
        }
    }

下面是我用来调用内核然后检查结果的代码段。

        CudafyModule km = CudafyTranslator.Cudafy();            
        _gpu = CudafyHost.GetDevice(eGPUType.Cuda);
        _gpu.LoadModule(km);

        float[,] Output = new float[SDS.dateTime.Length,2];
        float[] pm = new float[]{0.004f};

        //Otherwise need to allocate then specify the pointer in the CopyToDevice so it know which pointer to add data to
        float[] dev_tpc = _gpu.CopyToDevice(pm);
        float[] dev_p = _gpu.CopyToDevice(SDS.p);                                         
        float[] dev_s = _gpu.CopyToDevice(SDS.s);                                        
        float[,] dev_o = _gpu.CopyToDevice(Output);                                           
        float[] dev_dt = _gpu.CopyToDevice(SDS.dateTime);                                     


        dim3 grid = new dim3(20000, 1, 1);
        dim3 block = new dim3(1024, 1, 1);

        Stopwatch sw = new Stopwatch();
        sw.Start();

        _gpu.Launch(grid, block).WorkerKernelOnGPU(dev_tpc,dev_p, dev_s, dev_dt, dev_o);
        _gpu.CopyFromDevice(dev_o, Output);

        sw.Stop();      //0.29 seconds
        string resultGPU = sw.Elapsed.ToString();  
        sw.Reset();

        //Variables used to record errors.
        bool failed = false;
        float[,] wrongValues = new float[Output.Length, 3];
        int counterError = 0;

        //Check the GPU values are as expected. If not record GPU value, Expected value, position.
        for (int i = 0; i < 20480000; i++)
        {
            float gpuValue = Output[i, 0];
            if (SDS.dateTime[i] == gpuValue) { }

            else
            {
                failed = true;
                wrongValues[counterError, 0] = gpuValue;
                wrongValues[counterError, 1] = SDS.dateTime[i];
                wrongValues[counterError, 2] = (float)i;
                counterError++;
            }
        }

我只有一张显卡可供我使用,所以我无法快速检查卡是否有错误。这张卡不到 8 个月,买的时候是新的。

关于可能导致上述错误的任何想法?

谢谢你的时间。

编辑: 刚刚尝试将我的 gtx 660 降低到 660 的库存速度。但仍然遇到错误。

Edit2我用过_gpu.FreeMemory;确定我是否超出了卡的内存。不过,我还有 1,013,202,944 字节。

Edit3我刚刚将输出数组的数据类型更改为 long 而不是 float。我现在似乎卡上有超过 500MB 的可用空间,但我仍然从相同的值得到错误的结果,即 i = 16,777,217。我想这似乎表明这可能与问题所在的索引有关?

4

1 回答 1

1
    float threadIndex = thread.threadIdx.x;
    float blockIndex = thread.blockIdx.x;
    float threadsPerBlock = thread.blockDim.x;
    int tickPosition = (int)(threadIndex + (blockIndex * threadsPerBlock));

问题是我使用float作为ThreadIndex等。一旦将其更改为int,问题就解决了。

是时候让这个傻瓜远离电脑了。

于 2013-07-03T15:10:28.753 回答