我有一个非常稀疏的矩阵,密度约为0.01
,尺寸为20000 x 500000
。我正试图用犰狳加载它
sp_mat V;
V.load(filename, coord_ascii);
文件格式是
row column value
但这花了太长时间。 Python可以解析文件并用它来填充字典,比犰狳可以创建这个矩阵更快。我该怎么做呢?
矩阵将用整数填充。
任何意见,将不胜感激!
这只是犰狳的一个问题。当逐行读取时,C ++会毫无问题地迭代文件,但将值分配给arma::sp_mat
的速度非常慢。
犰狳文件规定
“使用批量插入构造函数通常比使用元素访问运算符连续插入值快得多”
所以这是我能想到的最好的
sp_mat get(const char *filename) {
vector<long long unsigned int> location_u;
vector<long long unsigned int> location_m;
vector<double> values;
ifstream file(filename);
int a, b, c;
while(file >> a >> b >> c) {
location_u.push_back(a);
location_m.push_back(b);
values.push_back(c);
}
umat lu(location_u);
umat lm(location_m);
umat location(join_rows(lu, lm).t());
return V(location, vec(values));
}
它现在以合理的速度运行,每秒约100万行。
我今天在尝试使用Armadillo的.load()
加载100MB CSV时遇到了同样的问题。这太慢了。
由于@Enrico Borba回答他正在使用std :: ifstream进行自己的文件读取,结果非常惊人,这里是我自己的代码,使用ifstream将CSV文件加载到Armadillo的mat类型。
例如,如果您尝试执行此操作,则加载文件将花费太多时间:
arma::mat A;
A.load("file.csv", arma::csv_ascii);
所以这是一个替代方案,比上面的代码快一千多:
arma::mat readCSV(const std::string &filename, const std::string &delimeter = ",")
{
std::ifstream csv(filename);
std::vector<std::vector<double>> datas;
for(std::string line; std::getline(csv, line); ) {
std::vector<double> data;
// split string by delimeter
auto start = 0U;
auto end = line.find(delimeter);
while (end != std::string::npos) {
data.push_back(std::stod(line.substr(start, end - start)));
start = end + delimeter.length();
end = line.find(delimeter, start);
}
data.push_back(std::stod(line.substr(start, end)));
datas.push_back(data);
}
arma::mat data_mat = arma::zeros<arma::mat>(datas.size(), datas[0].size());
for (int i=0; i<datas.size(); i++) {
arma::mat r(datas[i]);
data_mat.row(i) = r.t();
}
return data_mat;
}
然后你可以替换它如下:
arma::mat A = readCSV("file.csv");