gpt4 book ai didi

C++ Eigen 稀疏矩阵乘法比 python scipy.sparse 慢得多

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:29:22 30 4
gpt4 key购买 nike

编辑:性能上的巨大差异是由于测试中的错误造成的,如果设置正确,Eigen 会快 2 到 3 倍。

我注意到使用 C++ 的稀疏矩阵乘法 Eigen库比使用 Python 慢得多 scipy.sparse图书馆。我在 ~0.03 秒内在 scipy.sparse 中实现了在 ~25 秒内在 Eigen 中实现的效果。也许我在 Eigen 中做错了什么?

这里是 Python 代码:

from scipy import sparse
from time import time
import random as rn

N_VALUES = 200000
N_ROWS = 400000
N_COLS = 400000

rows_a = rn.sample(range(N_COLS), N_VALUES)
cols_a = rn.sample(range(N_ROWS), N_VALUES)
values_a = [rn.uniform(0,1) for _ in xrange(N_VALUES)]

rows_b = rn.sample(range(N_COLS), N_VALUES)
cols_b = rn.sample(range(N_ROWS), N_VALUES)
values_b = [rn.uniform(0,1) for _ in xrange(N_VALUES)]

big_a = sparse.coo_matrix((values_a, (cols_a, rows_a)), shape=(N_ROWS, N_COLS))
big_b = sparse.coo_matrix((values_b, (cols_b, rows_b)), shape=(N_ROWS, N_COLS))

big_a = big_a.tocsr()
big_b = big_a.tocsr()

start = time()

AB = big_a * big_b;

end = time()

print 'time taken : {}'.format(end - start)

C++代码:

#include <iostream>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <Eigen/Dense>
#include <Eigen/Sparse>

using namespace Eigen;

std::vector<long> gen_random_sample(long min, long max, long sample_size);
double get_random_double(double min, double max);
std::vector<double> get_vector_of_rn_doubles(int length, double min, double max);

int main()
{

long N_COLS = 400000;
long N_ROWS = 400000;
long N_VALUES = 200000;

SparseMatrix<double> big_A(N_ROWS, N_COLS);
std::vector<long> cols_a = gen_random_sample(0, N_COLS, N_VALUES);
std::vector<long> rows_a = gen_random_sample(0, N_COLS, N_VALUES);
std::vector<double> values_a = get_vector_of_rn_doubles(N_VALUES, 0, 1);

for (int i = 0; i < N_VALUES; i++)
big_A.insert(cols_a[i], cols_a[i]) = values_a[i];
// big_A.makeCompressed(); // slows things down

SparseMatrix<double> big_B(N_ROWS, N_COLS);
std::vector<long> cols_b = gen_random_sample(0, N_COLS, N_VALUES);
std::vector<long> rows_b = gen_random_sample(0, N_COLS, N_VALUES);
std::vector<double> values_b = get_vector_of_rn_doubles(N_VALUES, 0, 1);

for (int i = 0; i < N_VALUES; i++)
big_B.insert(cols_b[i], cols_b[i]) = values_b[i];
// big_B.makeCompressed();

SparseMatrix<double> big_AB(N_ROWS, N_COLS);

clock_t begin = clock();

big_AB = (big_A * big_B); //.pruned();

clock_t end = clock();
double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
std::cout << "Time taken : " << elapsed_secs << std::endl;

}

std::vector<long> gen_random_sample(long min, long max, long sample_size)
{
std::vector<long> my_vector(sample_size); // THE BUG, is right std::vector<long> my_vector

for (long i = min; i != max; i++)
{
my_vector.push_back(i);
}

std::random_shuffle(my_vector.begin(), my_vector.end());

std::vector<long> new_vec = std::vector<long>(my_vector.begin(), my_vector.begin() + sample_size);

return new_vec;
}

double get_random_double(double min, double max)
{
std::uniform_real_distribution<double> unif(min, max);
std::default_random_engine re;
double a_random_double = unif(re);
}

std::vector<double> get_vector_of_rn_doubles(int length, double min, double max)
{
std::vector<double> my_vector(length);
for (int i=0; i < length; i++)
{
my_vector[i] = get_random_double(min, max);
}
return my_vector;
}

我编译了:g++ -std=c++11 -I/usr/include/eigen3 time_eigen.cpp -o my_exec -O2 -DNDEBUG

我是否缺少使用 Eigen 快速进行稀疏乘法的方法?

最佳答案

如果您在编译时没有使用 -DNDEBUG,那么您会发现您的矩阵已损坏,因为您多次插入相同的元素,而插入方法不允许这样做。

将它们替换为 coeffRef(i,j) += value 或使用文档中推荐的三元组列表。在这个小修复之后,C++ 代码需要 0.012s,我的计算机上的 Python 需要 0.021s。请注意,您无法从这两个数字真正推断出哪个更快,因为输入矩阵并不完全相同,但至少它们的顺序相同。

关于C++ Eigen 稀疏矩阵乘法比 python scipy.sparse 慢得多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25100079/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com