我试图在运行内核之前在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以下进行,那可能会浪费。
谢谢。
答案 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)];
}
}
}
其他选项也是可能的,比如使用本地内存,但这是一项繁琐的工作....