1

在最坏的情况下,此示例是否在 GPU 全局内存中分配 testCnt * xArray.Length 存储?如何确保仅将阵列的一份副本传输到设备?GpuManaged 属性似乎可以达到这个目的,但它并不能解决我们意外的内存消耗。

void Worker(int ix, byte[] array)
{
    // process array - only read access
}

void Run()
{
    var xArray = new byte[100];
    var testCnt = 10;
    Gpu.Default.For(0, testCnt, ix => Worker(ix, xArray));
}

编辑

更精确形式的主要问题:每个工作线程是否获得 xArray 的新副本,或者是否所有线程都只有一个 xArray 副本?

4

2 回答 2

2

您的示例代码应在上分配100 bytes内存,在. (.Net 增加了一些开销,但我们可以忽略它)GPU100 bytesCPU

由于您正在使用implicit memory,因此需要分配一些资源来跟踪该内存(基本上它所在的位置:)CPU/GPU

现在...您可能会看到CPU认为的内存消耗更大。

其原因可能是由于内核编译发生在运行中。AleaGPU 必须将你的IL代码编译成 .cuda 编译器,然后将其转换LLVM成. 当您第一次运行内核时会发生这种情况。所有资源和非托管 dll 都加载到内存中。LLVMPTX

可能就是你所看到的。

testCnt对分配的内存量没有影响。

编辑*

一个建议是以明确的方式使用内存。它更快更高效:

    private static void Run()
    {
        var input = Gpu.Default.AllocateDevice<byte>(100);
        var deviceptr = input.Ptr;

        Gpu.Default.For(0, input.Length, i => Worker(i, deviceptr));

        Console.WriteLine(string.Join(", ", Gpu.CopyToHost(input)));
    }

    private static void Worker(int ix, deviceptr<byte> array)
    {
        array[ix] = 10;
    }
于 2017-10-04T00:31:29.070 回答
1

尝试使用显式内存:

static void Worker(int ix, byte[] array)
{
    // you must write something back, note, I changed your Worker
    // function to static!
    array[ix] += 1uy;
}

void Run()
{
    var gpu = Gpu.Default;
    var hostArray = new byte[100];
    // set your host array
    var deviceArray = gpu.Allocate<byte>(100); 
    // deviceArray is of type byte[], but deviceArray.Length = 0, 
    assert deviceArray.Length == 0
    assert Gpu.ArrayGetLength(deviceArray) == 100
    Gpu.Copy(hostArray, deviceArray);
    var testCnt = 10;
    gpu.For(0, testCnt, ix => Worker(ix, deviceArray));
    // you must copy memory back
    Gpu.Copy(deviceArray, hostArray);
    // check your result in hostArray
    Gpu.Free(deviceArray);
}
于 2017-10-04T09:40:44.793 回答