从多个线程并行读取同一文件的不同段

Muh*_*rel 5 c# storage multithreading nfs go

我需要从网络连接存储平台读取大文件(50-500 GB)的不同部分,并对其进行一些处理,并且我需要非常快速地完成此操作。

我正在使用 .net5、golang 和 c++ 编写应用程序,并发布适用于所有平台(Windows、Linux、MacOS)的代码

当我为 Linux 和 MacOS 发布下面的并行代码时,它工作得很好,并且与单线程方法相比,我获得了并行读取的好处(例如 4x-32x 取决于 CPU 核心的数量)。

然而,使用相同的硬件配置和相同的代码,与单线程方法相比,我在使用并行方法的 Windows 机器上没有得到任何性能影响。

另一个意想不到的行为是,当我在 Linux 平台上使用 GOLANG 编写相同的逻辑时,不同的发行版显示不同的行为。例如,只有当存储设备使用 NFS 协议挂载时,我的代码才能在 ubuntu 上进行并行读取。然而,在 CentOS 中,它可以通过两种配置(NFS 和块存储)进行并行读取。

所以我很困惑。

  1. 如果问题出在操作系统上,那么为什么我用 GOLANG 编写的代码可以在 NFS 上进行并行读取,而在使用 Ubuntu 时却不能在块存储上进行并行读取?
  2. 如果问题是语言(c#或GO),那么为什么C#应用程序可以在Linux(Ubuntu或CentOS)上进行并行读取,而不能在Windows(Win Server 2019)上进行并行读取?
  3. 如果问题出在网络存储设备挂载的协议上,那么为什么我在使用CentOS的时候,所有场景都能实现并行读取呢?

另外,您还可以在下面找到我为此场景准备的基准测试工具。

存储基准测试

存储基准-csharp

我知道这个问题是一个非常小众的问题,只对使用网络存储设备的人感兴趣,但如果某些操作系统或存储或软件人员可以对此发表评论,我会尝试我的更改。谢谢大家。

C# 中的单线程方法

//Store max of each section
int[] maxBuffer = new int[numberOfSections];

using (FileStream streamSource = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.Asynchronous))
{
    for (int index = 0; index < numberOfSections; index++)
    {
        byte[] sectionBuffer = new byte[1024L*20L];
        streamSource.Position = (((long)sectionBuffer.Length + numberOfBytesToSkip) * (long)index)%streamSource.Length;
        streamSource.Read(sectionBuffer, 0, sectionBuffer.Length));
        maxBuffer[index] = sectionBuffer.Max();
    }
}
Console.WriteLine(maxBuffer.Sum());
Run Code Online (Sandbox Code Playgroud)

并行方法 C#

//Store max of each section
int[] maxBuffer = new int[numberOfSections];

Parallel.For(0, numberOfSections, index =>
{
    using (FileStream streamSource = new FileStream(filePathOfLargeFile, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.Asynchronous))
    {
        byte[] sectionBuffer = new byte[1024L*20L];
        streamSource.Position = (((long)sectionBuffer.Length + numberOfBytesToSkip) * (long)index)%streamSource.Length;
        streamSource.Read(sectionBuffer, 0, sectionBuffer.Length);
        maxBuffer[index] = sectionBuffer.Max();
    }
});
Console.WriteLine(maxBuffer.Sum());
Run Code Online (Sandbox Code Playgroud)

我附上一张图像来可视化上面代码的实现。 在此输入图像描述