首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在C++中快速加载数值数据

在C++中快速加载数值数据
EN

Stack Overflow用户
提问于 2011-12-16 20:38:28
回答 2查看 673关注 0票数 3

我正在开发一个特征检测程序,它使用了图像中各种地标的统计模型。该模型使用了大约100个不同的地标,每个地标的相关数据由16个双面矩阵组成,每个矩阵的大小约为160x160。

目前,我正在为每个地标使用一个文本文件,并将每个矩阵的值存储为一个空格分隔的行。为了读取数据,我每次从每个文件中读取一行,并将其传递给一个函数,该函数从该行生成一个字符串流,然后每次从该流读取矩阵的值。

在我的电脑上,这需要大约90秒的时间来加载-4000万肯定有一种更快捷的方法,但我在谷歌上没有发现任何有用的东西,而且我对这类事情也没有经验。

如有任何建议,我将不胜感激。

编辑: Loki让我发布代码,所以我在下面展示了它。每个地标都调用一次loadFromFile。每个里程碑文件的第一行说明模型对这个地标使用了多少级别(每个级别使用四个矩阵;默认情况下有四个级别)。这是个可怕的烂摊子,但我不知道为什么这么慢。

代码语言:javascript
复制
void loadFromFile(string filename)
{
    ifstream modelData(filename.c_str(), ifstream::in);
    string line;    
    getline(modelData,line);
    int numberOfLevels = atoi(line.c_str());

    for(size_t ii = 0; ii < numberOfLevels; ++ii)
        readProfileStats(modelData);        

    modelData.close();              
}

void readProfileStats(ifstream& fileStream)
{
    string line;
    getline(fileStream, line);
    Vector meanProfile = readMatrixFromString(line);

    getline(fileStream, line);
    Matrix principalComponents = readMatrixFromString(line);

    getline(fileStream, line);  
    Matrix covarianceMatrixInverse = readMatrixFromString(line);

    m_statsLevels.push_back(ProfileStats(meanProfile, principalComponents, covarianceMatrixInverse));
}

Matrix readMatrixFromString(const string& line)
{
    stringstream stream(line);

    size_t numRows;
    size_t numCols; 

    stream >> numRows;  
    stream >> numCols;      

    Matrix matrix(numRows,numCols);

    for(int ii = 0; ii < numRows; ++ii)
    {                                       
        for(int jj = 0; jj < numCols; ++jj)             
            stream >> matrix(ii,jj);                                    
    }                                                       

    return matrix;                      
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-12-16 21:47:48

试着使用scanf库:

r1.cpp

代码语言:javascript
复制
> cat r1.cpp 

#include <iostream>
int main()
{
    double x;
    long   count = 0;
    while(std::cin >> x)
    {
        ++count;
    }
    std::cout << count << ": " << x << "\n";
}

r2.cpp

代码语言:javascript
复制
> cat r2.cpp 

#include <iostream>
#include <stdio.h>

int main()
{
    double x;
    long   count = 0;
    while(fscanf(stdin, "%lf", &x) == 1)
    {
        ++count;
    }
    std::cout << count << ": " << x << "\n";
}

结果系列

代码语言:javascript
复制
> g++ -O3 r1.cpp -o r1
> time (cat t | ./r1)
40000000: 9.36e+08

real    0m57.669s
user    0m56.992s
sys 0m1.688s
> g++ -O3 r2.cpp -o r2
> time (cat t | ./r2)
40000000: 9.36e+08

real    0m14.419s
user    0m13.897s
sys 0m1.352s

因此,使用IOstream读取4000万个数字所花费的时间比我预期的要长大约60秒。而只用了15秒的扫描。所以大约快4倍。

我也做了同样的事情,但只是写二进制值的双子文件。

请注意,您必须将它们写成二进制文件,当然,您还需要丢失所有类型、安全性和可移植性。

代码语言:javascript
复制
double x;
std::cout.write((char*)&x, sizeof(x));

r1b.cpp

代码语言:javascript
复制
> cat r1b.cpp 

#include <iostream>
int main()
{
    double x;
    long   count = 0;
    while(std::cin.read((char*)&x, sizeof(double)))
    {
        ++count;
    }
    std::cout << count << ": " << x << "\n";
}

r2b.cpp

代码语言:javascript
复制
> cat r2b.cpp 

#include <iostream>
#include <stdio.h>

int main()
{
    double x;
    long   count = 0;
    while(fread(&x, sizeof(double), 1, stdin) == 1)
    {
        ++count;
    }
    std::cout << count << ": " << x << "\n";
}

结果二进制

代码语言:javascript
复制
> time (cat t2 | ./r1b )
40000000: 9.36e+08

real    0m3.930s
user    0m3.592s
sys 0m0.984s
> time (cat t2 | ./r2b )
40000000: 9.36e+08

real    0m2.110s
user    0m1.840s
sys 0m0.804s
票数 1
EN

Stack Overflow用户

发布于 2011-12-16 21:29:42

正如注释中所建议的那样,这里的问题是必须将数据从文本转换为数值。这可以通过以二进制格式存储数据来完全消除。有些库可以处理这个问题,比如hdf5。使用这样一个流行的库有很多好处,因为您可以得到一个完整的预先构建的工具链,以及除了C++之外的许多其他语言的支持。但是,缺点是,在学习如何使用这些系统之前,还需要做一些很好的工作。如果这是一个一次性的研究项目,我建议您强烈考虑另一种更简单的方法:一旦您的结构第一次创建,只需将数据结构fwrite或mmap映射到磁盘文件中即可。然后,创建一个函数,将该二进制文件直接映射到您的数据结构中。给程序调用mmap函数而不是解析函数的选项。你会看到这样做会大大加快速度。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8539846

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档