我当前的解析器如下所示 - 读取~10MB CSV到STL向量需要~30秒,这对我来说太慢了,因为我已经超过100MB,需要在每次运行程序时读取。任何人都可以就如何提高性能提出一些建议?实际上,在普通的C中它会更快吗?
int main() {
std::vector<double> data;
std::ifstream infile( "data.csv" );
infile >> data;
std::cin.get();
return 0;
}
std::istream& operator >> (std::istream& ins, std::vector<double>& data)
{
data.clear();
// Reserve data vector
std::string line, field;
std::getline(ins, line);
std::stringstream ssl(line), ssf;
std::size_t rows = 1, cols = 0;
while (std::getline(ssl, field, ',')) cols++;
while (std::getline(ins, line)) rows++;
std::cout << rows << " x " << cols << "\n";
ins.clear(); // clear bad state after eof
ins.seekg(0);
data.reserve(rows*cols);
// Populate data
double f = 0.0;
while (std::getline(ins, line)) {
ssl.str(line);
ssl.clear();
while (std::getline(ssl, field, ',')) {
ssf.str(field);
ssf.clear();
ssf >> f;
data.push_back(f);
}
}
return ins;
}
注意:我也有openMP可供使用,内容最终将用于使用CUDA进行GPGPU计算。
答案 0 :(得分:5)
你可以通过一次阅读文件而不是两次来获得一半的时间。
虽然预测向量是有益的,但它永远不会支配运行时,因为I / O总是会慢一些。
另一种可能的优化可能是没有字符串流的读取。像(未经测试的)
之类的东西int c = 0;
while (ins >> f) {
data.push_back(f);
if (++c < cols) {
char comma;
ins >> comma; // skip comma
} else {
c = 0; // end of line, start next line
}
}
如果您可以省略,
并仅按空格分隔值,则可能是偶数
while (ins >> f)
data.push_back(f);
或
std::copy(std::istream_iterator<double>(ins), std::istream_iterator<double>(),
std::back_inserter(data));
答案 1 :(得分:3)
在我的机器上,您的保留代码大约需要1.1秒,填充代码需要8.5秒。
添加std :: ios :: sync_with_stdio(false);对我的编译器没有任何影响。
以下C代码需要2.3秒。
int i = 0;
int j = 0;
while( true ) {
float x;
j = fscanf( file, "%f", & x );
if( j == EOF ) break;
data[i++] = x;
// skip ',' or '\n'
int ch = getc(file);
}
答案 2 :(得分:2)
尝试拨打
std::ios::sync_with_stdio(false);
在您的计划开始时。这会禁用cin
/ cout
和scanf
/ printf
之间的(据称相当慢)同步(我自己从未尝试过这种方式,但经常看到这样的建议,例如here)。请注意,如果执行此操作,则无法在程序中混合C ++样式和C样式IO。
(另外,Olaf Dietsche完全正确地只读过一次文件。)
答案 3 :(得分:-1)