Parallel processing 如何进一步优化这个OpenCL内核

Parallel processing 如何进一步优化这个OpenCL内核,parallel-processing,opencl,Parallel Processing,Opencl,我试图在OpenCL中实现hausdorff距离,下面的内核构成了它的基础,或者我认为它是这样的,因为我仍然需要完全实现它。也就是说,我能得到一些建议吗?或者有没有办法优化这个内核?基本上,我如何删除内核函数中调用helper函数的for循环 OpenCL内核及其辅助函数: void helper( int a_1, __global int* b_1, __global int* c_1 ){ int i = get_global_id(0); c_1[i] =

我试图在OpenCL中实现hausdorff距离,下面的内核构成了它的基础,或者我认为它是这样的,因为我仍然需要完全实现它。也就是说,我能得到一些建议吗?或者有没有办法优化这个内核?基本上,我如何删除内核函数中调用helper函数的for循环

OpenCL内核及其辅助函数:

void helper( int a_1, __global int* b_1, __global int* c_1 ){
        int i = get_global_id(0);
        c_1[i] = a_1 - b_1[i];
}

__kernel void test_call( __global int* a,             //input buffer of size [100000, 1]
                         __global int* b,             //input buffer of size [100000, 1]
                         __global int* c ){           //output buffer of size [100000, 1]
        for ( int iter = 0 ; iter < 100000 ; iter++ ){
                helper ( a[iter], b, c );
                // once array c is obtained by calling the above function,
                // it will be used in further processing that will take place inside 
                // this for loop itself
}
void helper(int a_1、\u全局int*b_1、\u全局int*c_1){
int i=获取全局id(0);
c_1[i]=a_1-b_1[i];
}
__内核void test_调用(_global int*a,//大小为[100000,1]的输入缓冲区)
__全局int*b,//大小为[100000,1]的输入缓冲区
__全局int*c){//大小为[100000,1]的输出缓冲区
用于(国际热核试验堆=0;国际热核试验堆<100000;国际热核试验堆++){
助手(a[iter],b,c);
//一旦通过调用上述函数获得数组c,
//它将用于内部进行的进一步处理
//这是循环本身
}
基本上,我在这里试图做的是用输入缓冲区“b”中的每个元素减去输入缓冲区“a”中的每个元素。复杂性为O(n2)


顺便说一句,这个简单的实现本身会在2.5秒内产生结果。一个串行实现需要几分钟才能完成执行。

我想,您的代码仍然可以通过使用平铺方案来改进。 在您当前的实现中,所有工作项都加载缓冲区“a”的所有值。目前它们以非同步方式加载。通过平铺方案,您可能可以更好地利用缓存体系结构,让设备仅从片外内存加载“a”的每个值一次

这个方案最好在这里解释:(PDF文件)

在您的例子中,平铺并行方法可能类似于下面的伪代码

forall values of b in parallel {
    foreach tile q {
        forall work_items p in work_group in parallel {
            local[p] = a[q*tile_size + p]
        }
        synchronize work items in work group
        foreach body j in tile q {
            c[i] = local[j] - b[i];
        }
        synchronize work items in work group
    }
}

关键思想是,每个工作项都可以利用缓冲区“a”的值,缓冲区“a”的值已经由同一组中的其他工作项加载。然后(理想情况下)每个“a”项只能从内存中提取一次,并从缓存中平铺1次。

我想,通过使用平铺方案,您的代码仍然可以得到改进。 在您当前的实现中,所有工作项都加载缓冲区“a”的所有值。目前它们以非同步方式加载。通过平铺方案,您可能可以更好地利用缓存体系结构,让设备仅从片外内存加载“a”的每个值一次

这个方案最好在这里解释:(PDF文件)

在您的例子中,平铺并行方法可能类似于下面的伪代码

forall values of b in parallel {
    foreach tile q {
        forall work_items p in work_group in parallel {
            local[p] = a[q*tile_size + p]
        }
        synchronize work items in work group
        foreach body j in tile q {
            c[i] = local[j] - b[i];
        }
        synchronize work items in work group
    }
}

关键思想是每个工作项都可以利用缓冲区“a”的值,缓冲区“a”的值已经由同一组中的其他工作项加载仅从内存中提取一次,并从缓存中平铺\u size-1次。

我建议删除对helper的函数调用并使其内联。此外,使用pragma展开for循环以使GPU更有效地利用ILP。我建议删除对helper的函数调用并使其内联。此外,使用pragma展开for循环为了让GPU更有效地开发ILP。谢谢你的建议。我会尝试并返回……:)使用缓存内存将提高执行时间(至少在GPU上)。你也可以把你的输入数据当作向量来利用SIMD指令(不是每个OpenCL编译器都会自动矢量化你的内核)。@ @ USE108398,我把WarfarA的建议与TILLL结合起来。我的执行时间比Beo更快。谢谢你的建议。我会试试这个,然后再回来……:)使用缓存内存将提高执行时间(至少在GPU上)。你也可以考虑你的输入数据作为利用SIMD指令的向量。(并不是每个openCL编译器都会自动对内核进行矢量化)。@user1083498,我将华法拉的建议与平铺相结合。我的执行时间比以前快了。谢谢。