流解析算法速度问题
stream parsing algorithm speed issue
我写了一个波前 Obj 解析器类,用于将 obj 模型导入我的 OpenGL 项目。 我在调试模式下测试了该类,发现它慢得令人难以忍受。
代码有效,我进行了明显的调整,以确保它与合理实用的效率一样高。
尽管如此,加载我的测试文件,一个 12mb obj 文件,运行到大约 330,000 行文本,需要一分钟多的时间来解析。
沮丧的是,我有一个谷歌,果然,我不是第一个遇到这个问题的人。
这个在 gamedev.net 上发布查询的家伙只是在发布模式下运行他的算法,在Visual Studio IDE和whammo之外,性能可以接受。 这也对我有用,我的~70秒减少到~3秒。
我对算法进行了一些分析,瓶颈在于对 std::getline 的调用,以及以下内容:
sstream >> sToken;
其中 sstream 是 std::stringstream,sToken 是 std::string(预先保留空格(。
问题
为什么 IDE 在运行我的解析算法时如此慢得令人难以置信(即使在发布模式下( - 在通过 IDE 运行代码时,我能做些什么来加快速度(F5 - 运行项目(? 这使得调试变得非常慢。 IDE 是将代码/钩子注入可执行文件以通过 IDE 运行,还是可以将其归结为缓存未命中或其他原因?
优化
我通过文件进行了两次传递,在第一次传递中,我只计算令牌类型 - 以便我可以保留空间(而不是迭代增长存储顶点、法线、texcoord、面等的向量(
sLineBuffer.reserve( 100 );
sToken.reserve(10);
while( sstream.good() )
{
sstream >> sToken;
getline( sstream, sLineBuffer );
if( sToken.compare("f") == 0 )
nFaces ++;
else if( sToken.compare("v") == 0 )
nVertices ++;
else if( sToken.compare("vn") == 0 )
nNormals ++;
else if( sToken.compare("vt") == 0 )
nTextures ++;
else if( sToken.compare("g") == 0 )
nGroups ++;
}
m_Vertices.reserve( nVertices );
m_Normals.reserve( nNormals );
m_TexCoords.reserve( nTextures );
m_Faces.reserve( nFaces );
m_Groups.reserve( nGroups );
第一次传递的成本很低(调试模式下为 ~8 秒,在 IDE 外部的发布模式下为 ~0.3 秒(,并且效率节省巨大(将解析时间从调试模式下的 ~180 秒减少到 ~60 秒(。
我还将整个文件读入字符串流,以便将磁盘访问从等式中剔除:
// Read entire file from disk into memory
fstream stream;
stringstream sstream;
stream.open( m_sFilename.c_str(), std::ios::in );
sstream << stream.rdbuf();
stream.close();
此外,在可能的情况下,在整个算法中,我尝试提前为 std::string 保留空间,以便它们不会按字符调整大小:
sLineBuffer.reserve( 100 );
sToken.reserve(10); // etc
证明是对Visual Studio IDE运行方式的误解。
按 F5 将在调试模式下运行,无论你是在调试还是发布版本中。
我了解了 Ctrl+F5 将调试器从等式中取出的内容(但只有当您运行发布版本时,您才会在执行此操作时看到速度提高(。
我还了解到,在这种情况下,stdio 可能是一个更好的解决方案。 我将不得不按照建议重写我的算法以使用 fscanf,并在此处报告我的发现,尽管我对这个想法感到畏缩。
STL 的编写方式是期望编译器对许多小函数进行大量内联。不过,调试器允许您进入所有精彩的抽象层,并且在调试模式下您为此付出了高昂的代价,因为它无法内联任何内容。
通常我不会给出以下建议,但在解析 OBJ 文件的上下文中,我建议只扔掉 STL 并依靠老式的 fscanf
语句。您会发现在调试期间有显著的提高,在发布模式下速度也有明显的提高。
- 警告处理为错误这里有什么问题
- 最小硬币更换问题(自上而下方法)
- 为"adjacent"变量赋值时出现问题
- 我的神经网络不起作用 [XOR 问题]
- 在Ubuntu 16.04上安装Cilk时出现问题
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 编译包含字符串的代码时遇到问题
- Project Euler问题4的错误解决方案
- 问题:什么是QAbstractItemView::NoEditTriggers的反面
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 静态数据成员的问题-修复链接错误会导致编译器错误
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 一个关于在C++中重载布尔运算符的问题
- 首要问题的答案让值班员搞错了
- 在Webots C++中将速度设置为差速轮的问题
- 流解析算法速度问题
- 使用"最大化速度"而不是"最小化大小"的堆问题
- 我的项目中指向int的速度问题
- OpenCV速度问题