В этот ссылка из netlib указывает M как:
На входе M указывает количество строк матрицы
op (A) и матрицы C. M должно быть не меньше нуля.
Без изменений при выходе.
Так что, если я хочу использовать матрицу 3×10 в качестве A, но я хочу использовать ее сопряженную для zgemm (TRANSA = ‘C’), что я должен ввести как M? 3 или 10?
Также, когда я использовал другие подпрограммы LAPACK, я вводил двумерные матрицы как 1D, например, A [3 * 3] вместо A [3] [3], и после вызова подпрограммы я просто использовал A для матрицы. Могу ли я сделать то же самое с не квадратные матрицы? A [3 * 10] вместо A [3] [10]?
Я кодирую на C ++.
Соглашение об именовании / уточнение
Прежде чем дать ответ и для большей ясности, важно иметь в виду этот факт:
в то время как
Комментарии:
Все документы Blas / Lapack, которые вы найдете на netlib.org, используют соглашение США
Я (как европеец) должен признать, что конвенция США более логична, чем индексы (i, j) и (m, n), следующие за тот же алфавитный порядок
Чтобы избежать такой двусмысленности, я обычно использую:
B / Ответы
B.1 / гемм
void cblas_zgemm(CBLAS_LAYOUT layout,
CBLAS_TRANSPOSE opA,
CBLAS_TRANSPOSE opB,
const int M, <-------------- I_Size of op(A)
const int N, <-------------- J_Size of op(B)
const int K, <-------------- J_Size of op(A)
const void* alpha,
const void* A,
const int lda,
const void* B,
const int ldb,
const void* beta,
void* C,
const int ldc);
В глаголах если ТРАНСА = ‘Т’ Вы должны взять размеры транспонировать Матрица
Реализация для вызова cblas_zgemm
может выглядеть так:
const Size_t opA_I_size = (opA == CblasNoTrans) ? A.I_size() : A.J_size();
const Size_t opA_J_size = (opA == CblasNoTrans) ? A.J_size() : A.I_size();
const Size_t opB_I_size = (opB == CblasNoTrans) ? B.I_size() : B.J_size();
const Size_t opB_J_size = (opB == CblasNoTrans) ? B.J_size() : B.I_size();
cblas_zgemm(CblasColMajor,
opA,
opB,
opA_I_size,
opB_J_size,
opA_J_size,
alpha,
A.data(),
A.ld(),
B.data(),
B.ld(),
beta,
C.data(),
C.ld());
Б.2 / Расположение памяти
Для совместимости Blas / Lapack и, в более общем случае, для обработки чисел …
никогда не используйте A [I_size] [J_size], но всегда A [I_size * J_size]
(причина в том, что в одном случае у вас есть массив указателей, в другом случае у вас есть непрерывный блок памяти, который намного удобнее для векторизации, дружелюбия к кешу и т. д.)
Чтобы быть более точным за
основной столбец (стиль Фортран) у вас есть: A [ld * J_size]
основная строка (стиль C): A [I_size * ld]
(где л.д. это ведущее измерение)
Обновления:
Даже если вы кодируете в C ++ Я рекомендую использовать соглашение Фортрана (колонка Major). Lapacke притворяется, что поддерживает основной режим строки, однако, под капотом, он просто копии Ваша матрица в основной макет столбца перед вызовом запрошенной подпрограммы. Так что это дополнительное средство — всего лишь иллюзия (в отношении перфораторов). Чтобы быть более точным, это Функция LAPACKE_dge_trans (). Вы можете проверить код Лапаке, чтобы увидеть, что эта функция используется почти везде, как только Layout=RowMajor
(см. lapacke_dgesv_work () код например).
Также обратите внимание, что если вы хотите общие шаги («произвольное начальное измерение» в направлениях I и J), вы можете использовать библиотеку, например Blis вместо Блас. Настоящим преимуществом является возможность создавать произвольные 2D-виды тензоров. Этот выбор зависит от вашего приложения, я не знаю, имеете ли вы в виду манипуляцию с тензором.
B.3 / Размеры матрицы
Если ваши матрицы всегда будут такими маленькими, как 3×10 blas / lapack, это не лучший выбор (для исполнения). Рассмотрите возможность использования библиотеки как собственный или же Blaz.
Других решений пока нет …