【问题标题】:Running a kernel with CUDAfy .NET using OpenCL asynchronously使用 OpenCL 异步运行带有 CUDAfy .NET 的内核
【发布时间】:2016-08-12 23:20:41
【问题描述】:

我正在尝试使用 CUDAfy .NET 对我的 GPGPU 进行异步内核调用。

当我将值传递给内核并将它们复制回主机时,我并不总是得到我期望的值。

我有一个带有字节 Bar 的结构 Foo:

[Cudafy]
public struct Foo {
    public byte Bar;
}

我有一个我想调用的内核:

[Cudafy]
public static void simulation(GThread thread, Foo[] f)
{
    f[0].Bar = 3;
    thread.SyncThreads();
}

我有一个 streamID = 1 的线程(我尝试使用多个线程,并注意到了这个问题。但减少到一个线程似乎并没有解决这个问题)。

        //allocate
        streamID = 1;
        count = 1;
        gpu.CreateStream(streamID);
        Foo[] sF = new Foo[count];
        IntPtr hF = gpu.HostAllocate<Foo>(count);
        Foo[] dF = gpu.Allocate<Foo>(sF);
        while (true)
        {
            //set value
            sF[0].Bar = 1;

            byte begin = sF[0].Bar;

            //host -> pinned
            GPGPU.CopyOnHost<Foo>(sF, 0, hF, 0, count);

            sF[0].Bar = 2;

            lock (gpu)
            {
                //pinned -> device
                gpu.CopyToDeviceAsync<Foo>(hF, 0, dF, 0, count, streamID);
                //run
                gpu.Launch().simulation(dF);
                //device -> pinned
                gpu.CopyFromDeviceAsync<Foo>(dF, 0, hF, 0, count, streamID);
            }
            //WAIT
            gpu.SynchronizeStream(streamID);


            //pinned -> host
            GPGPU.CopyOnHost<Foo>(hF, 0, sF, 0, count);

            byte end = sF[0].Bar;
        }
        //de-allocate
        gpu.Free(dF);
        gpu.HostFree(hF);
        gpu.DestroyStream(streamID);

首先我在 GPU 上创建一个流。

我正在创建一个大小为 1 (sF) 的常规结构 Foo 数组并将其 Bar 值设置为 1。然后我也在主机 (hF) 上为 Foo 创建固定内存。我还在设备上为 Foo (dF) 创建内存。

我将结构的 Bar 值初始化为 1,然后将其复制到固定内存(作为检查,我在复制到固定后将结构的值设置为 2,稍后您会看到原因)。然后我使用锁来确保我可以完全访问 GPU,并将副本排队到 dF、内核运行和来自 dF 的副本。在这一点上,我不知道这一切何时会真正在 GPU 上运行......所以我可以调用 SynchronizeStream 在主机上等待,直到设备完成。

完成后,我可以将固定内存 (hF) 复制到共享内存 (sF)。当我获得该值时,它通常是 3(在设备上设置)或 1(这意味着该值未在内核中设置,或者新值未复制到固定内存)。我知道固定内存被复制到结构中,因为结构永远不会有值 2。

在多次运行中,一小部分运行结果不是 begin=1 和 end=3。它始终是 begin=1,end=1,并且发生率约为 5-10%。

我不知道为什么会这样。我知道它通常会突出显示竞争条件,但通过调用同步调用,我希望异步调用以可预测的方式工作。

为什么我会在这段代码中遇到这种问题?

非常感谢!

-菲尔

【问题讨论】:

    标签: visual-studio asynchronous opencl


    【解决方案1】:

    我刚刚发现了正在发生的问题。虽然启动是异步完成的...我没有包含启动的流。

    将我的发布更改为:

    gpu.Launch(gridsize,blocksize,streamID).simulation(dF);

    解决了这个问题。似乎启动发生在流 0 上,并且流 1 和 2 正在同步。所以有时数据被设置,有时它没有。竞争条件。

    【讨论】:

      猜你喜欢
      • 2020-03-15
      • 2015-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多