88 inline void Im2Col(
const float *input,
89 int channels,
int height,
int width,
91 int strideH,
int strideW,
93 float *columns)
noexcept
95 const int outH =
ConvOutDim(height, kH, strideH, padH);
96 const int outW =
ConvOutDim(width, kW, strideW, padW);
97 const int colWidth = outH * outW;
99 for (
int c = 0; c < channels; ++c)
101 for (
int kh = 0; kh < kH; ++kh)
103 for (
int kw = 0; kw < kW; ++kw)
105 const int rowIdx = (c * kH + kh) * kW + kw;
106 float *destRow = columns + (size_t)rowIdx * colWidth;
108 for (
int oh = 0; oh < outH; ++oh)
110 const int inRow = oh * strideH - padH + kh;
111 float *dst = destRow + (size_t)oh * outW;
113 if (inRow < 0 || inRow >= height)
115 std::memset(dst, 0, (
size_t)outW *
sizeof(
float));
120 input + ((size_t)c * height + inRow) * width;
124 const int first = padW > kw ? padW - kw : 0;
125 const int last = width + padW - kw < outW
131 for (; ow < first; ++ow)
134 const float *s = src + first - padW + kw;
135 float *d = dst + first;
136 const int count = last - first;
139#if defined(__AVX512F__)
140 for (; i + 16 <= count; i += 16)
143 _mm512_loadu_ps(s + i));
144#elif defined(__AVX2__) || defined(__AVX__)
145 for (; i + 8 <= count; i += 8)
148 _mm256_loadu_ps(s + i));
149#elif defined(__SSE__)
150 for (; i + 4 <= count; i += 4)
153 _mm_loadu_ps(s + i));
156 for (; i < count; ++i)
159 for (ow = last; ow < outW; ++ow)
164 for (
int ow = 0; ow < outW; ++ow)
167 ow * strideW - padW + kw;
170 (inCol < 0 || inCol >= width)
214 int channels,
int height,
int width,
216 int strideH,
int strideW,
218 float *outputImage)
noexcept
220 const int outH =
ConvOutDim(height, kH, strideH, padH);
221 const int outW =
ConvOutDim(width, kW, strideW, padW);
222 const int colWidth = outH * outW;
224 for (
int c = 0; c < channels; ++c)
226 for (
int kh = 0; kh < kH; ++kh)
228 for (
int kw = 0; kw < kW; ++kw)
230 const int rowIdx = (c * kH + kh) * kW + kw;
231 const float *srcRow =
232 columns + (size_t)rowIdx * colWidth;
234 for (
int oh = 0; oh < outH; ++oh)
236 const int inRow = oh * strideH - padH + kh;
238 if (inRow < 0 || inRow >= height)
243 ((size_t)c * height + inRow) * width;
246 srcRow + (size_t)oh * outW;
250 const int first = padW > kw ? padW - kw : 0;
251 const int last = width + padW - kw < outW
255 const float *s = src + first;
256 float *d = dst + first - padW + kw;
257 const int count = last - first;
260#if defined(__AVX512F__)
261 for (; i + 16 <= count; i += 16)
263 const __m512 a = _mm512_loadu_ps(s + i);
264 const __m512 b = _mm512_loadu_ps(d + i);
267 _mm512_add_ps(a, b));
269#elif defined(__AVX2__) || defined(__AVX__)
270 for (; i + 8 <= count; i += 8)
272 const __m256 a = _mm256_loadu_ps(s + i);
273 const __m256 b = _mm256_loadu_ps(d + i);
276 _mm256_add_ps(a, b));
278#elif defined(__SSE__)
279 for (; i + 4 <= count; i += 4)
281 const __m128 a = _mm_loadu_ps(s + i);
282 const __m128 b = _mm_loadu_ps(d + i);
289 for (; i < count; ++i)
294 for (
int ow = 0; ow < outW; ++ow)
297 ow * strideW - padW + kw;
299 if (inCol >= 0 && inCol < width)
300 dst[inCol] += src[ow];
void Im2Col(const float *input, int channels, int height, int width, int kH, int kW, int strideH, int strideW, int padH, int padW, float *columns) noexcept
Rearranges a single (channels, height, width) input image into a (channels*kH*kW, outH*outW) column m...
Definition Im2Col.h:88
void Col2Im(const float *columns, int channels, int height, int width, int kH, int kW, int strideH, int strideW, int padH, int padW, float *outputImage) noexcept
The adjoint of Im2Col(): scatters a (channels*kH*kW, outH*outW) column-gradient buffer back into a (c...
Definition Im2Col.h:213
int ConvOutDim(int inDim, int kernel, int stride, int pad) noexcept
Computes a single convolution output dimension (height or width) from its corresponding input dimensi...
Definition Im2Col.h:57