Как собственные операторы интерпретируются как функции MKL внутри? - PullRequest
0 голосов
/ 12 июня 2018

Eigen - очень удобная библиотека, которая может выразить математическую формулу в краткой и интуитивно понятной форме.Я знаю, что у Эйгена есть ленивые концепции оценки, которые могут представлять цепочку операций в классах выражений и эффективно оценивать ее при необходимости.Я также знаю, что Eigen можно использовать с MKL.Однако мне любопытно, какие выражения можно передавать в вызовы MKL cblas.При каких условиях они не подлежат передаче?Существуют ли какие-либо общие правила, которые могут помочь мне выяснить, что можно передать?

Обычно мне интересны следующие случаи:

MatrixXd A, B, C;
VectorXd a, b, c;
double w1, w2, w3;

b += w1 * A * a;  // can be done through dgemv
b += w1 * A.transpose() * a;  // can be done through dgemv
C += w2 * A * B;  // can be done through dgemm
C += w2 * A.transpose() * B;  // can be done through dgemm
C += w2 * A. topRows(5).transpose() * B;  // can be done through dgemm

D = A * B * C;    // cannot be done in one func call through cblas

Примечание: комментарии не являются результатом переноса Eigen.Это идеальный результат.Я не уверен, может ли Эйген передавать их.

Существует также еще один вопрос: когда Эйген будет выделять временную память в этой цепочке операций?Существуют ли общие правила, которые могут помочь мне выяснить, произошло ли какое-либо распределение?

Ответы [ 2 ]

0 голосов
/ 12 июня 2018

Чтобы завершить ответ chtz, все ваши гипотезы верны (при условии, что вы добавите декоратор .noalias()), и в более общем случае любое выражение или подвыражение, которое выглядит как gemv / gemm, будет преобразовано в один вызов, включая транспонирование, блоки, сопряженные и т. д. В этом модульном тесте можно найти примеры подсчета количества временных, поэтому 0 означает один вызов, похожий на blas, 1 означает, что временный будет создан до илипосле звонкого звонка и т. д.

0 голосов
/ 12 июня 2018

Прежде всего, чтобы избежать временных значений в ваших примерах, вы должны написать

b.noalias() += w1 * A * a;

Это потому, что Eigen не может сказать во время компиляции, что b, A и a делаютне псевдоним, а потому оценивает продукт как временный. Подробнее см. Здесь .

Godbolt-demo: https://godbolt.org/g/VSfekp (Обратите внимание, что -DEIGEN_USE_BLAS по существу эквивалентно -DEIGEN_USE_MKL_ALL, но Godbolt в настоящее время не поддерживает MKL).


К вашему актуальному вопросу: Чтобы определить, нужна ли операции временная операция, вы можете скомпилировать с -DEIGEN_RUNTIME_NO_MALLOC и разделами окружения, которые, по вашему мнению, не должны выделяться на

Eigen::set_is_malloc_allowed(false); // mallocs after this cause assertions
// some code
Eigen::set_is_malloc_allowed(true); // mallocs are allowed again

Для этого требуется, чтобы у объекта результата был правильный размер перед входом в этот раздел.

Кроме того, это не поможет для выражений фиксированного размера, поскольку они никогда не будут выделять кучу памяти, но для выражений фиксированного размераиспользование MKL обычно менее эффективно, чем Eigen (который в зависимости от размера полностью развернет необходимые операции).

...