При поиске библиотеки программного обеспечения, которая в сжатом виде предназначена для умножения малых матриц, можно взглянуть на https://github.com/hfp/libxsmm. Ниже код запрашивает специализированное ядро матрицы в соответствии с типичными параметрами GEMM (обратите внимание, что применяются некоторые limitations).
double alpha = 1, beta = 1;
const char transa = 'N', transb = 'N';
int flags = LIBXSMM_GEMM_FLAGS(transa, transb);
int prefetch = LIBXSMM_PREFETCH_AUTO;
libxsmm_blasint m = 23, n = 23, k = 23;
libxsmm_dmmfunction xmm = NULL;
xmm = libxsmm_dmmdispatch(m, n, k,
&m/*lda*/, &k/*ldb*/, &m/*ldc*/,
&alpha, &beta, &flags, &prefetch);
Учитывая выше код, можно продолжить и запустить «XMM» для целого ряда (маленьких) матриц без конкретной структуры данных (ниже кода также использует «местоположение предварительной выборки»).
if (0 < n) { /* check that n is at least 1 */
# pragma parallel omp private(i)
for (i = 0; i < (n - 1); ++i) {
const double *const ai = a + i * asize;
const double *const bi = b + i * bsize;
double *const ci = c + i * csize;
xmm(ai, bi, ci, ai + asize, bi + bsize, ci + csize);
}
xmm(a + (n - 1) * asize, b + (n - 1) * bsize, c + (n - 1) * csize,
/* pseudo prefetch for last element of batch (avoids page fault) */
a + (n - 1) * asize, b + (n - 1) * bsize, c + (n - 1) * csize);
}
В дополнение к контролю ручного контура, как показано выше, libxsmm_gemm_batch (или libxsmm_gemm_batch_omp) могут быть использованы (см ReadTheDocs). Последнее полезно, если существуют структуры данных, описывающие серию операндов (матрицы A, B и C).
Существует две причины, почему эта библиотека обеспечивает превосходную производительность: (1) специализированная специализация по коду с использованием технологии генерации кода в памяти и (2) загрузка следующих матричных операндов при вычислении текущего продукта.
(Учитывая один ищет что-то, что хорошо сочетается с C/C++, эта библиотека поддерживает его. Тем не менее, он не стремится к CUDA/Thrust.)
Это кажется хороший подход. Любые идеи о накладных расходах, связанных с использованием причудливых итераторов более консервативного подхода? – nes
Что характеризует более консервативный подход? Вы имеете в виду использование метода strided range для создания полноразмерного масштабного вектора? –
Мне было любопытно, сколько накладных расходов на операцию 'transform (numbers, iterator)' вводится по сравнению с обычной операцией 'transform (numbers, other numbers). – nes