При вычислении произведения двух разреженных матриц Eigen работает исключительно хорошо для матриц четного размера. Например:
#include <iostream>
#include <random>
#include <numeric>
#include <chrono>
#include <vector>
#include <Eigen/eigen>
using namespace Eigen;
typedef std::chrono::high_resolution_clock myclock;
typedef double Scalar_t;
typedef Triplet<Scalar_t> Triplet_t;
typedef SparseMatrix<Scalar_t> Sparse_t;
Sparse_t make_sparse_matrix(int row_size, int col_size, Scalar_t sparsity, Scalar_t min, Scalar_t max)
{
std::mt19937 generator;
std::uniform_real_distribution<Scalar_t> val_dist(min, max);
auto random_real = std::bind(val_dist, generator);
int non_zero_entries = sparsity * (row_size * col_size);
std::uniform_int_distribution<int> row_dist(0, row_size - 1);
auto random_row = std::bind(row_dist, generator);
std::uniform_int_distribution<int> col_dist(0, col_size - 1);
auto random_col = std::bind(col_dist, generator);
std::vector<Triplet_t> triplets;
triplets.reserve(non_zero_entries);
for (int i = 0; i < non_zero_entries; i++)
{
int row = random_row();
int col = random_col();
Scalar_t value = random_real();
triplets.emplace_back(row, col, value);
}
Sparse_t result(row_size, col_size);
result.setFromTriplets(triplets.begin(), triplets.end());
return result;
}
int main()
{
int row_size = 2000;
int col_size = 5000;
Scalar_t sparsity = 0.1;
Scalar_t min = 0;
Scalar_t max = 1e-8;
Sparse_t A = make_sparse_matrix(row_size, col_size, sparsity, min, max);
auto start = std::chrono::high_resolution_clock::now();
Sparse_t ATA = (A.transpose() * A).pruned().eval();
auto stop = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(stop - start);
std::cout << duration.count() << " milliseconds\n";
return 0;
}
8,167 миллисекунд, и это здорово! Однако, если вы слегка измените размер матрицы на
int row_size = 2000-1;
int col_size = 5000-1;
18,525 миллисекунд, это может быть нормально, если я не запустил тест выше! Конечно, если я тогда попытаюсь:
int row_size = 2000-2;
int col_size = 5000-2;
4,505 миллисекунд!
int row_size = 2000-3;
int col_size = 5000-3;
18,314 миллисекунд!
Что здесь происходит? Я использую Visual Studio 2017, режим выпуска, нет openmp, все по умолчанию.