Недавно я работал с матрицами Eigen, полученными из необработанных буферов, и заметил этот любопытный случай:
#include <eigen3/Eigen/Dense>
int main(int argc, char const *argv[]) {
/* code */
const int M = 320;
const int N = 640;
const int K = 320;
const int alpha = 2;
const int beta = 1;
Eigen::Matrix<int32_t, Eigen::Dynamic,Eigen::Dynamic> A = Eigen::Matrix<int32_t, Eigen::Dynamic,Eigen::Dynamic>::Random(M,K);
Eigen::Matrix<int32_t, Eigen::Dynamic,Eigen::Dynamic> B = Eigen::Matrix<int32_t, Eigen::Dynamic,Eigen::Dynamic>::Random(K,N);
Eigen::Matrix<int32_t, Eigen::Dynamic,Eigen::Dynamic> C = Eigen::Matrix<int32_t, Eigen::Dynamic,Eigen::Dynamic>::Random(M,N);
//Following http://eigen.tuxfamily.org/dox/TopicWritingEfficientProductExpression.html
C.noalias() += (A*alpha)*(B*beta); //WORKS
C.noalias() += A*B;
Eigen::Map<Eigen::Matrix<int32_t, M, K, Eigen::ColMajor> > map_a(A.data());
Eigen::Map<Eigen::Matrix<int32_t, K, N, Eigen::ColMajor> > map_b(B.data());
Eigen::Map<Eigen::Matrix<int32_t, M, N, Eigen::ColMajor> > map_c(C.data());
map_c.noalias() += map_a*map_b; //WORKS
map_c.noalias() += (map_a*alpha)*(map_b*beta); //COMPILE ERROR HERE
return 0;
}
Если у меня большие размеры матрицы, я не могу выделить в стеке или получуOBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG
, поэтому я использую собственный динамический распределитель.
Однако, похоже, что если у меня есть необработанный буфер, и я сопоставляю его с матрицей, я не могу выполнить BLAS 3-подобное умножение gemm (C+= (alpha*A)*(beta*B)
) из-за ошибки компиляции: OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG
.Если я сделаю простой C += A*B
, все будет работать, как и ожидалось.
В этом примере я отображаю необработанный буфер из матрицы, выделенной Eigen, но в принципе это может быть необработанный буфер из чего угодно (например,std::vector
).
Есть идеи, что здесь происходит?Насколько я могу сказать, здесь все должно быть выделено кучей, и даже если бы этого не было, почему C += A*B
будет работать с отображенными матрицами памяти, а C+= (alpha*A)*(beta*B)
не будет?
Приветствия,
Ник