Проблемы с производительностью нечетных продуктов с разреженной матрицей в Eigen - PullRequest
2 голосов
/ 28 февраля 2020

При вычислении произведения двух разреженных матриц 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, все по умолчанию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...