c有效地读取每个X字节中的前几个字节
我想读取文件的每个X * 16字节中的前16个字节.我编写的代码可以工作,但由于函数调用很多,所以代码很慢.
std::vector<Vertex> readFile(int maxVertexCount) { std::ifstream in = std::ifstream(fileName,std::ios::binary); in.seekg(0,in.end); int fileLength = in.tellg(); int vertexCount = fileLength / 16; int stepSize = std::max(1,vertexCount / maxVertexCount); std::vector<Vertex> vertices; vertices.reserve(vertexCount / stepSize); for (int i = 0; i < vertexCount; i += stepSize) { in.seekg(i * 16,in.beg); char bytes[16]; in.read(bytes,16); vertices.push_back(Vertex(bytes)); } in.close(); } 有人可以给我一些建议来提高这段代码的性能吗? 解决方法
它可能不是函数调用本身,而是非顺序访问模式,从大文件中选取小段.即使您只读取16个字节,存储子系统也可能会读取(并缓存)较大的块.您的访问模式对于典型的I / O是致命的.
(分析应该显示磁盘访问是否是瓶颈.如果是“许多函数调用”,CPU将是.) 那么,首先,你能改变这个要求吗? 你能少分散吗?例如.而不是读取顶点0,20,40,…,1000,读取顶点0,1,2,3,4,100,101,102,103,104,200,201,202,203,204,… – 来自文件“所有部分”的相同数量的顶点. 第二,特定于操作系统的优化. 一种解决方案是内存映射文件(Windows上的CreaterFileMapping,Linuxy系统上的mmap),如@Nim所建议的那样.这可以省略一个内存副本,但仍会读取整个文件. 对Linux无能为力,但在Windows上你有CreateFile的参数: > FILE_FLAG_NO_BUFFERING这基本上意味着你进行缓冲,让你更好地控制发生的缓存,但你不能无所畏惧地寻求阅读. 这些都不会解决您的访问模式的问题,但第一个可能会稍微调整它 – 特别是如果您的步骤大于磁盘扇区,第二个可以从子系统承受压力. 第三,快照. 对于特定的maxVertexCount,快照可能只是您操作的结果.或多个快照,如mipmapping.想法是通过顺序读取来替换分散的读取. 或者,快照可以以交错顺序存储数据.对于128个顶点,您可以按顺序存储顶点(粗略地,要注意off-by< -one,零vs-one-based和别名效果,以及我的错误): 64,32,96,16,48,80,112 8,24,56,72,88,120 …… 无论您是读取前3个或前7个或前15个还是前31个…值,样本都会在文件中均匀分布,就像您的原始代码一样.将它们重新排列在内存中会快得多 – 特别是如果它只是一小部分. 注意:您需要一个强大的算法来检测您的快照是否过时,而不管在不同文件系统上“最后写入日期”发生的许多有趣的事情.主文件中的“更改计数器”将是最安全的(尽管它会增加更改的成本). 第四,更改文件格式 (如果你可以控制那个) 优雅的选项是将这样的交错子集作为文件的一部分,以及原始顺序的完整顶点列表.有一个cutoff stepSize,这对此不再有太大帮助,可能是磁盘的2 *扇区/块大小.因此文件大小只会增加几个百分点.但是,写入会花费更多,顶点数量的变化会更加严重. 别名警告 如果这是为了获得“统计”或“视觉上足够”的采样,固定的stepSize可能会有问题,因为它可以创建数据中存在的任何模式的混叠效果(想想莫尔模式). 在这种情况下,随机抽样将是可取的.这可能听起来很可怕并使一些解决方案更难以实现,但通常是避免许多次优案例的最简单方法. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |