这更像是一个概念性问题。我正在使用的遗留代码具有C ++线程实现来模拟并行文件读取。它处理多线程文件读取的方式是只将一个数据块(比如2^20 bytes
)从文件传输到char* array
,然后多个线程读取该数组的专用部分。当线程完成时,它等待所有其他线程完成(即,使用condition_variable
上共享的unique_lock
)并完成最后一个线程,将下一个数据块从文件加载到数组中并继续该过程,直到读取整个文件。并行读取的原因是这些文件通常超过1 GB
并且非常耗时。加快速度约为6x
或更多。
我观察到一些奇怪的行为。当代码在物理机器中运行时(即使它是远程连接的),多线程文件读取始终正常工作。但是,如果它在虚拟机上运行,有时在读取后会丢失数据。我已调试每个线程只读一行,有时结果不正确。这表明错误结果的原因不是读取错误,而是缺少输入文件中的整行(.txt
)。如果我增加线程数(线程数越多,失败次数越多)并增加文件大小(即,如果文件大小大于char* array
的大小,我可以更频繁地重现错误结果)。这让我相信问题不在于多线程文件读取,而是与运行时环境(物理与虚拟机)有关。
我只是大声思考,想要看看是否有人经历过类似的行为,或者是否有任何关于为什么会出现此类行为的见解。我正在调查任何buffer overflow
问题,但到目前为止还没有发现任何问题。
编辑: 添加有关环境的更多信息
我正在使用Visual Studios 2013
所以使用MS Visual C++
编译器,所有物理机和虚拟机都是Windows Server 2012 R2
或Windows Server 2008 R2
64-bit
和{{1}可用的最小内存为x64-based processors
,可以升至32GB
。服务器使用不同版本的120GB
CPU。
答案 0 :(得分:3)
这几乎可以肯定意味着您的代码具有竞争条件,该条件通常很少发生,但是由VM上的条件引起。
由于间歇性可用内核或不同的时间切片或者甚至从相对自愿的更改到更抢占式的任务切换,可能不同的线程调度正在强调该问题。也有可能你错过了某处的错误检查,也许线读取功能有时会因为可恢复的IO错误而读取部分行,这些错误你没有检查但很少发生在真正的铁上。但是,由于您没有发布代码,我无法开始调试它。
TLDR 几乎可以肯定您的代码是错误的,而不是VM实现(假设它是主流的虚拟机管理程序)。
作为一个侧面点,尽管这与您的问题无关,但我不明白为什么您可能以这种方式执行此文件IO而不是mmap'文件并让线程从mmap读取。在大多数情况下,这将大大提高效率,并且在大多数操作系统中具有固有的线程安全性。