Open ysh329 opened 3 years ago
cl::NDRange CLContext::DefaultLocalWorkSize(
const cl::NDRange &gws,
register size_t max_ws,
const int &divisor /*=2*/,
const bool &reverse /*=false*/,
const size_t &user_def_max_ws /*=0*/) {
register size_t lx = reverse ? gws[2] : gws[0];
register size_t ly = gws[1];
register size_t lz = reverse ? gws[0] : gws[2];
max_ws = (user_def_max_ws > 0 && user_def_max_ws <= max_ws) ? user_def_max_ws
: max_ws;
max_ws = divisor > 1 ? max_ws / divisor : max_ws;
if (max_ws > 0) {
while (ly > max_ws) {
// replace mod with bit operate
ly = (ly & 0x01) ? 1 : ly >> 1;
}
while (ly * lz > max_ws) {
lz = (lz & 0x01) ? 1 : lz >> 1;
}
while (ly * lz * lx > max_ws) {
lx = (lx & 0x01) ? 1 : lx >> 1;
}
}
return reverse ? cl::NDRange{lz, ly, lx} : cl::NDRange{lx, ly, lz};
}
背景:增加该API的目的是:在X86 MacOS和X86 Linux系统上,OpenCL设备支持FP32精度计算,同时,也是为了验证一套opencl kernel代码的计算结果是正确的(因为FP16确实有累计系统误差的问题),而非Kernel代码有bug。
精度API提供3种精度设置:
类似AutoTune,只不过将实现的过程放在了CLRuntime中
,因为这部分需要作为build option作为参数传入opencl kernel里,子在opencl kernel内的精度用宏来表示如CL_DTYPE_float
表示定义CL_DTYPE
为float,计算精度为float,CL_DTYPE_half
同理。
static std::map<std::string, size_t> InitImageDimInfoWith(
const DDim& tensor_dim) {
size_t new_dims[] = {1, 1, 1, 1};
for (size_t j = 0; j < tensor_dim.size(); ++j) {
new_dims[4 - tensor_dim.size() + j] = tensor_dim[j];
}
size_t N, C, H, W;
N = new_dims[0];
C = new_dims[1];
H = new_dims[2];
W = new_dims[3];
size_t width = W * ((C + 3) / 4);
size_t height = H * N;
return std::map<std::string, size_t>({{"width", width}, {"height", height}});
}
如果维度不够4维如只有2维度,则将2维度前面补1
Paddle-Lite OpenCL后端主要分为如下4部分:
cl::Program
的创建;cl::Kernel
的创建、设置LocalWorkSize、GlobalWorkSize、AutoTune等;CLWrapper
的部分OpenCL API函数做框架层面的封装,如Image2D和Buffer的Malloc、Free等。其它琐碎的地方: