使用犰狳装载大型矩阵

时间:2017-04-20 04:41:06

标签: c++ sparse-matrix armadillo

我有一个非常稀疏的矩阵,密度约为0.01,维度为20000 x 500000。我试图用

加载犰狳
sp_mat V;
V.load(filename, coord_ascii);

文件格式为

row column value

但这太长了。 Python可以解析文件并用 way 填充字典,而不是犰狳可以创建这个矩阵。我该怎么做呢?

矩阵将用整数填充。

任何建议都将不胜感激!

更新

仅与Armadillo有关。当逐行读取时,C ++会毫无问题地迭代文件,但将值分配给arma::sp_mat的速度非常慢。

2 个答案:

答案 0 :(得分:4)

犰狳文件指定

  

"使用批量插入构造函数通常比使用元素访问运算符连续插入值快得多#34;

所以这是我能想到的最好的

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万行。

答案 1 :(得分:0)

我尝试使用Armadillo .load()尝试加载100MB CSV时遇到了同样的问题。它太慢了。

由于@Enrico Borba回答他正在使用std :: ifstream进行自己的文件读取,结果非常惊人,这里是我自己的代码,使用ifstream将CSV文件加载到Armadillo的垫子类型

例如,如果您尝试这样做,则加载文件需要花费太多时间:

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");