本文介绍GPU实现的Conv2DProgram。
卷积的实现
逻辑输出坐标:xRCorner,xCCorner。
卷积的基本流程:用高宽分别是filterHeightxfilterWidth的卷积核对输入数据做卷积。
要注意的是:输入数据和卷积核除了有高度和宽度之外,还有一个参数,深度convInfo.inChannels。
所以卷积就变成了:对逻辑输出坐标对应的所有深度的的通道,依次做getX()xgetW()的运算。所以这里出现了三次循环:外围是高宽。里面是深度。
for (int wR = 0; wR < ${filterHeight}; wR++) {
for (int wC = 0; wC < ${filterWidth}; wC++) {
for (int d1 = 0; d1 < ${convInfo.inChannels}; d1 ++) {
dotProd += getX(batch, xR, xC, d1)*getW(wR, wC, d1, d2);
}
}
}
于vec4运算比单独乘加要快。所以内部循环被解开成了:
- d1 < ${inputDepthNearestVec4},满足4的倍数的部分,一次加载四个通道的数据,并做乘加运算;
- ${inputDepthVec4Remainder, 4的余数部分,则分1,2,3三种情况来处理。
深度可分离卷积
测试代码生成的输出坐标函数是:
ivec4 getOutputCoords()