我正在尝试在OpenCL中实现卷积算法(使用Vivado HLS)。我试图在执行工作组之前将图像的一部分加载到本地内存中(例如,如果工作组为128 * 128,而卷积滤镜为5 * 5,则我将加载132 * 132像素)。如何编写内核,以便在工作组启动时仅将本地内存加载一次?
伪代码:
#define WKGRP_W 128
#define WKGRP_H 128
#define FILTER_SIZE 5
#define BUFFER_W WKGRP_W+FILTER_SIZE-1
#define BUFFER_H WKGRP_H+FILTER_SIZE-1
__kernel void __attribute__ ((reqd_work_group_size(WKGRP_W, WKGRP_H, 1)))
convolve(
const __global data_t* input,
__global data_t* output,
__constant data_t* filter_params
){
__local data_t img_buffer[BUFFER_H][BUFFER_W];
__local data_t output_buffer[WKGRP_H][WKGRP_W];
/**
* if (the workgroup is starting) {
* load data from input into img_buffer
* }
*/
filter(img_buffer, filter_params, get_local_id(0), get_local_id(1), output_buffer);
/**
* if (the workgroup is finished) {
* load data from output_buffer into output
* }
*/
}
答案 0 :(得分:0)
假设每个输入像素有一个工作项,则可以让每个线程将一个像素从全局内存加载到本地内存。
int x = get_local_id(0);
int y = get_local_id(1);
img_buffer[x][y] = input[...];
barrier(CLK_LOCAL_MEM_FENCE);
// filter here or whatever computation you need to perform
如果数据是对齐的,则可以通过强制转换为较大的数据类型来加快速度。有关更多详细信息,请参见this link。
编辑:让每个线程获取2个值,直到达到132
。当然,某些工作项可能最终在此过程中什么也不做
int x = get_local_id(0);
int y = get_local_id(1);
if (2*x < 132 && 2*y < 132) {
img_buffer[2*x][2*y] = input[...];
img_buffer[2*x][2*y + 1] = input[...];
img_buffer[2*x + 1][2*y] = input[...];
img_buffer[2*x + 1][2*y + 1] = input[...];
}
barrier(CLK_LOCAL_MEM_FENCE);
// filter here...
答案 1 :(得分:0)
您可以使用async_work_group_copy
执行到本地的复制。它将返回一个事件对象,您可以使用wait_group_events
立即对其进行等待。
或者同时执行一些不需要复制数据的其他处理。 (即:为过滤器计算一些因素)。为了使工作组忙。
//Copy input from global to local
event_t global2local = async_work_group_copy(img_buffer, input, size, 0);
wait_group_events(1, &global2local);
//Copy the buffer from local to global
event_t local2global = async_work_group_copy(output_buffer, output, size2, 0);
wait_group_events(1, &local2global);