OpenCL:在__global memory

时间:2015-08-10 17:53:46

标签: opencl

我试图在运行内核之前在2个全局内存之间移动一些数据 这里缓冲区包含需要在数组中写入的数据,但遗憾的是不连续:

void exchange_2_halo_write(
    __global float2 *array,
    __global float *buffer,
    const unsigned int im,
    const unsigned int jm,
    const unsigned int km
) {
const unsigned int v_dim = 2;
unsigned int i, j, k, v, i_buf = 0;

// Which vector component, ie along v_dim
for (v = 0; v < v_dim; v++) {
    // top halo
    for (k = 0; k < km; k++) {
        for (i = 0; i < im; i++) {
            ((__global float*)&array[i + k*im*jm])[v] = buffer[i_buf];
            i_buf++;
        }
    }
    // bottom halo
    for (k = 0; k < km; k++) {
        for (i = 0; i < im; i++) {
            ((__global float*)&array[i + k*im*jm + im*(jm-1)])[v] = buffer[i_buf];
            i_buf++;
        }
    }
    // left halo
    for (k = 0; k < km; k++) {
        for (j = 1; j < jm-1; j++) {
            ((__global float*)&array[j*im + k*im*jm])[v] = buffer[i_buf];
            i_buf++;
        }
    }
    // right halo
    for (k = 0; k < km; k++) {
        for (j = 1; j < jm-1; j++) {
            ((__global float*)&array[j*im + k*im*jm + (im-1)])[v] = buffer[i_buf];
            i_buf++;
        }
    }
}
}

这在C中工作得很好(有一些小的改动),对于我需要的数据大小(im = 150,jm = 150,km = 90,buf_sz = 107280),它运行大约0.02s。登记/> 我曾经期望相同的代码在GPU上更慢,但不是那么慢,它实际上需要大约90分钟来做同样的事情(大约250000倍慢!)。

简单地进行直接分配大约需要15分钟,这清楚地表明它不是可行的方式。

for (i = 0; i < buf_sz; i++) {
    array[i] = buffer[i];
}

在那种情况下,我看到我可以这样做:

int xid = get_global_id(0);
array[xid] = buffer[xid];

似乎很好/很快。
但是,我不知道如何调整它以使用我在第一个代码中的条件。

top和bottom_halo部分有im个连续的元素转移到数组,我认为这意味着可以轻松转移。可悲的是,left和right_halos没有。

使用更好的代码,我可以期望有点接近CPU时间吗?如果不可能在1s以下进行,那可能会浪费。

谢谢。

1 个答案:

答案 0 :(得分:1)

在回答之前,1评论。在内核中执行for循环时,如下所示:

for (i = 0; i < buf_sz; i++) {
    array[i] = buffer[i];
}

然后启动ie:512个工作项,你正在复制512次!! ,而不是与512个线程并行执行。显然,它会更慢!超过512倍!!!

那就是说,你可以用这种方式拆分它:

2D全局尺寸:km x max(im,jm)

void exchange_2_halo_write(
    __global float2 *array,
    __global float *buffer,
    const unsigned int im,
    const unsigned int jm
) {
const unsigned int v_dim = 2;
const unsigned int k = get_global_id(0);
const unsigned int i = get_global_id(1);
const unsigned int km = get_global_size(0);

// Which vector component, ie along v_dim
for (unsigned int v = 0; v < v_dim; v++) {
    if(i < im){
        // top halo
        ((__global float*)&array[i + k*im*jm])[v] = buffer[v*(2*km*im + 2*km*(jm-2))+km*i];
        // bottom halo
        ((__global float*)&array[i + k*im*jm + im*(jm-1)])[v] = buffer[v*(2*km*im + 2*km*(jm-2))+km*im+km*i];
    }

    if(i < jm-1 && i > 0){
        // left halo
        ((__global float*)&array[i*im + k*im*jm])[v] = buffer[v*(2*km*im + 2*km*(jm-2))+km*im*2+km*(i-1)];
        // right halo
        ((__global float*)&array[i*im + k*im*jm + (im-1))[v] = buffer[v*(2*km*im + 2*km*(jm-2))+km*im*2+km*(jm-2)+km*(i-1)];
    }
}
}

其他选项也是可能的,比如使用本地内存,但这是一项繁琐的工作....