如何进一步优化此OpenCL内核

时间:2012-10-23 16:42:31

标签: parallel-processing opencl

我正在尝试在OpenCL中实现hausdorff距离,并且以下内核构成了它的基础,或者我认为它确实如此,因为我仍然必须完全实现它。也就是说,我可以得到一些建议,还是有办法优化这个内核?基本上如何在内核函数中删除调用辅助函数的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
}

基本上我在这里要做的是用输入缓冲区'b'中的每个元素减去输入缓冲区'a'中的每个元素。复杂性将是O(n 2 )。

顺便说一句,这种天真的实现本身会在2.5秒内产生结果。此序列的实现将花费几分钟时间来完成执行。

1 个答案:

答案 0 :(得分:3)

我想,通过使用切片方案,您的代码仍然可以改进。 在当前实现中,所有工作项都会加载缓冲区“a”的所有值。目前他们以不同步的方式这样做。使用切片方案,您可以更好地利用缓存架构,让设备只从片外存储器加载一次“a”值。

此方案最好在此解释:http://software.intel.com/file/24571(PDF文件)。

在您的情况下,Tiled Parallel Approach看起来像下面的伪代码。

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
    }
}

关键思想是每个work_item都可以使用已经由同一组中的其他work_items加载的缓冲区'a'的值。然后(理想情况下)'a'的每个条目仅从内存中获取一次,并从缓存中获取tile_size-1次。