gpt4 book ai didi

c++ - 将文件映射多线程化为缓冲区数组

转载 作者:行者123 更新时间:2023-11-28 07:43:26 25 4
gpt4 key购买 nike

我正在尝试处理讨厌的大型xml和文本文档:〜40GB。
我在Windows 7上使用Visual Studio 2012。

我将使用“ Xerces”从xmls中获取标头/“页脚标记”。

我想映射文件的某个区域,例如60-120MBs。

将地图分为(3 *处理器/核心)相等的部分。将每个部分设置为缓冲区并将缓冲区加载到数组中。

然后,在新线程中的语句中使用(#processors / cores),我将在咀嚼缓冲区数组时同步计算字符/行/ xml周期。当一个缓冲区完成时,该过程将跳转到下一个“可用”缓冲区,并且完成的缓冲区将从内存中删除。最后,我将总结果添加到项目日志中。

之后,我将参考日志,按字符数/大小(或其他选项)将文件拆分到最接近的行或循环,并在页眉和“页脚标记”中放置所有拆分。

我这样做是为了可以通过具有多台计算机的网络将海量数据导入MySQL服务器。

我的问题是,如何使用新线程创建缓冲区数组和文件映射?

我可以用吗 :

赢得CreateFile

赢得CreateFileMapping

赢得MapViewOfFile

使用标准的ifstream操作和char缓冲区还是应该选择其他选项?

进一步说明:
我的想法是,如果让硬盘驱动器从一个位置和一个方向将文件流传输到内存中,就可以使用计算机的全部处理能力来咀嚼单独但相等的缓冲区。

〜Flavor:这就像是一个Shepard,试图从一个装有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%。现在,从firefox中打开的〜50个选项卡中加载的大多数RAM是600 + MB,在Visual Studio中为60MB,然后再等等。

重要提示:在测试过程中,运行代码的程序(仅一个窗口和一个对话框)似乎将其自己的工作和专用的ram集转储到了300K ish,并且没有响应考试。我肯定需要为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

但...

我想指出的是,在对资源mon和任务管理器中的进程进行轮询时,它清楚地显示出第一个核心的使用率为75-90%,第二个核心的使用率为25-50%(对于我已经打开的一些小背景知识,这是相当标准的),然后将硬盘驱动器放在..等待... 50%。大约100%的磁盘时间峰值,但也有些低点,为25%。所有这些基本上意味着在两个不同线程之间分配缓冲区处理将非常有益。它将使用所有系统资源,但这就是我想要的。我将在今天晚些时候拥有可用的原型进行更新。

主要更新:
经过一番学习,终于完成了我的项目。无需文件映射。只有一堆矢量字符。我已经成功构建了一个动态执行的文件流行和字符计数器。
好消息是,在5.8GB的文件BOOYA上,从之前的10-15分钟标记变为了大约3-4分钟!

最佳答案

答案很简短:是的,您可以使用这些功能。

对于读取数据,这可能是将文件内容映射到内存的最有效方法,因为它省去了将内存复制到应用程序的缓冲区中的麻烦,只需将其直接读取到应该存放的位置即可。因此,只要您有足够的地址空间就没问题-64位计算机当然应该有足够的空间,在32位系统中,它可能更多是稀缺资源-但对于几百MB的部分,它不应该这将是一个巨大的问题。

但是,使用多线程我一点也不确信。我有一个公平的想法,即读取一个大文件的多个部分会适得其反。这将增加磁头在磁盘上的移动量,这是传输速率的很大一部分。对于“普通”系统,您可以依靠大约50-100MB / s的传输速率。如果系统具有某种RAID控制器或类似的RAID控制器,则可能是它的两倍-非常奇特的RAID控制器可以达到三倍。

因此,读取40GB内容大约需要3-15分钟。

CPU可能不会很忙,并且运行多个线程很可能会降低系统的整体性能。

您可能想要保留一个线程用于读取,一个线程用于写入,并且仅在有足够数量的数据后才实际写出数据,以免磁盘上的读/写头不必要地移动。

关于c++ - 将文件映射多线程化为缓冲区数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15366154/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com