OpenBLAS sgemm, особые требования? иногда я получаю нан

У меня есть это объявление в моем заголовке где-то:

typedef float real;
typedef int integer;
extern "C" {
extern int sgemm_(char *transa, char *transb,
  integer *m, integer *n, integer *k,
  const real *alpha,
  const real *a, integer *lda,
  const real *b, integer *ldb,
  const real *beta,
  real *c, integer *ldc);
}

Затем я ссылаюсь на библиотеку OpenBLAS (или, возможно, также на другие библиотеки BLAS, например, MKL). И тогда я прямо звоню sgemm_ в моем коде C++. (Код должен в принципе работать с любой библиотекой BLAS.)

Я не уверен, что это плохая идея или нет. Или о чем я должен позаботиться. Например, мне нужно специальное выравнивание? Или мне нужно позаботиться в многопоточной среде?

(Например, я немного искал код OpenBLAS (SGEMM специально для ядра), и, похоже, он предполагает особые требования к выравниванию (но, возможно, я ошибся).)

В основном, кажется, работает нормально. За исключением того, что в некоторых случаях (недетерминированных, может быть, в 10% случаев, для некоторых сложных тестовых случаев, я получаю nan в моем результате; и это, кажется, не происходит в нашем производственном коде).

1 ответ

У вас не должно возникнуть проблем с вызовом BLAS из C++. OpenBLAS является широко используемой библиотекой, и не ожидается, что у нее будет такая базовая проблема.

BLAS - это библиотека Fortran, поэтому вы должны иметь в виду, что она использует формат хранения Fortran для двумерных матриц. Это означает, что матрицы - это отдельные блоки памяти, в которых хранятся двумерные матрицы в главном порядке столбцов.

Вы не можете использовать двумерные динамически распределенные массивы (т.е. double **a;) так как выделенная память будет фрагментирована. Также, если вы используете двумерные статические массивы (т.е. double a[5][4]), вы должны иметь в виду, что в C/C++ порядок хранения является основным. В этом случае вы все еще можете использовать BLAS, но вы должны учитывать, что матрица транспонирована.

Я бы предложил использовать векторы с одним указателем (double *a;) и получить доступ к элементам матрицы вручную (a[i+j*m]).

OpenBLAS имеет многопоточную поддержку. При компиляции вы можете определить, будет ли он использовать потоки или OpenMP или ничего.

Что касается получаемой ошибки, я бы посоветовал проверить вашу память, поскольку такое поведение обычно основано на ошибках в памяти. В любом случае я не ожидал, что ошибка будет sgemm реализация, но так, как это вызывается.

Другие вопросы по тегам