【发布时间】:2013-03-12 16:02:35
【问题描述】:
我正在尝试处理令人讨厌的大型 xml 和文本文档:~40GBs。 我在 Windows 7 上使用 Visual Studio 2012。
我将使用“Xerces”从 xml 中获取页眉/“页脚标签”。
我想映射文件的一个区域,比如说.. 60-120MB。
将地图分成(3 * 个处理器/内核)相等的部分。将每个部分设置为缓冲区并将缓冲区加载到数组中。
然后在新线程中使用 (#processors/cores) while statments,我将在浏览缓冲区数组时同步计算字符/行/xml 周期。当一个缓冲区完成时,该进程将跳转到下一个“可用”缓冲区,并且完成的缓冲区将从内存中删除。最后,我会将总结果添加到项目日志中。
之后,我将参考日志,按字符数/大小(或其他选项)将文件拆分到最近的行或循环,然后将页眉和“页脚标签”放入所有拆分中。
我这样做是为了可以通过具有多台计算机的网络将大量数据导入 MySQL 服务器。
我的问题是,如何使用新线程创建缓冲区数组和文件映射?
我可以使用吗:
赢得创建文件
赢得创建文件映射
赢得 MapViewOfFile
使用标准 ifstream 操作和字符缓冲区,还是应该选择其他方式?
进一步说明: 我的想法是,如果我可以让硬盘驱动器将文件从一个位置和一个方向流式传输到内存中,我就可以利用机器的全部处理能力来咀嚼单独但相等的缓冲区。
~味道:这有点像一个牧羊人试图从一个带有 3-6 个大桶的大垃圾箱中舀出食物,只有两条手臂用于需要留在围栏区域内的 X 只羊。但它们都以光速运动。
这里有一些想法或建议可能会对我有所帮助。 任何想法都是最受欢迎的。谢谢。
while(getline(my_file, myStr))
{
characterCount += myStr.length();
lineCount++;
if(my_file.eof()){
break;
}
}
这是测试运行时唯一的代码。 2小时30+分钟。在具有 2GB RAM 的双核 1.6Mhz 笔记本电脑上运行程序的总处理器为 45-50%。现在加载的大部分 RAM 是 600+MB,在 Firefox 中打开约 50 个选项卡,Visual Studio 为 60MB,然后等等。
重要提示:在测试过程中,运行代码的程序(只有一个窗口和一个对话框)似乎转储了它自己的工作和私有内存集,降至 300K 左右,并且没有响应测试的长度。我确定我需要为 while 语句创建另一个线程。但这意味着没有文件被读入缓冲区。 CPU 在整个运行过程中都在努力跟上硬盘驱动器的最小努力。
附: CPU 瓶颈的进一步证明。通过我的无线网络将整个文件传输到另一台计算机可能需要 20 分钟。其中包括读取进程和套接字捕获以在另一台计算机上写入进程。
更新
我用这个可爱的小东西从之前的测试时间缩短到大约 15-20 分钟,这与 Mats Petersson 所说的一致。
while (my_file.read( &bufferOne[0], bufferOne.size() ))
{
int cc = my_file.gcount();
for (int i = 0; i < cc; i++)
{
if (bufferOne[i] == '\n')
lineCount++;
characterCount++;
}
currentPercent = characterCount/onePercent;
SendMessage(GetDlgItem(hDlg, IDC_GENPROGRESS), PBM_SETPOS, currentPercent, 0);
}
当然,这是一个单循环,它实际上比之前的测试表现得更合适。该测试比上面显示的使用 Getline 的紧密循环快约 800%。我将此循环的缓冲区设置为 20MB。我从:SOF - Fastest Example
中提取了此代码但是...
我想指出的是,在资源监视器和任务管理器中轮询进程时,它清楚地显示第一个内核的使用率为 75-90%,第二个内核的使用率为 25-50%(对于一些较小的背景内容来说,这是相当标准的我已经打开),硬盘在..等待它... 50%。一些 100% 的磁盘时间峰值,但也有一些 25% 的低点。所有这些基本上意味着在两个不同的线程之间拆分缓冲区处理很可能是一个好处。它将使用所有系统资源,但是..这就是我想要的。当我有工作原型时,我会在今天晚些时候更新。
主要更新: 经过一番学习,终于完成了我的项目。不需要文件映射。只有一堆矢量字符。我已经成功构建了一个动态执行的文件流线和字符计数器。 好消息,从之前的 10-15 分钟标记到 5.8GB 文件的约 3-4 分钟,BOOYA!~
【问题讨论】:
-
这不是 SAX 设计的线性解析吗?我不认为它会允许多台机器这样做。
-
之后我使用多台机器进行导入过程。文件的解析和分割只能在一个系统上完成。
-
好的,所以第一件相当明显的事情是,一个 5.6GB 的文件可能包含大约 100M 的换行符,所以这是 100M 的除法操作(大约 20-30 个时钟周期)和 100M 的调用SendMessage() 和 GetDlgItem()。这两者都可能比字符串的输入读数更重。添加类似
if ((lineCount & 1024) == 0) { currentPercent = ....; SendMessage(...); } -
不确定您是否在下面看到我的评论,但在构建/运行测试之后添加了 SendMessage 和当前百分比位。它只是带有字符数、行数和 break 语句的 while 语句。
-
不过你的权利。我不需要它发送 1 亿个 SendMessage 请求,但确实可以顺利过渡;)
标签: c++ multithreading winapi buffer