16

假设我有一个数据集,它是一个存储在 4TB HDD ext4 文件系统上的文件中的 1e12 32 位整数(4 TB)数组。

考虑到数据很可能是随机的(或者至少看起来是随机的)。

// pseudo-code
for (long long i = 0; i < (1LL << 40); i++)
   SetFileIntAt(i) = GetRandInt();

此外,考虑到我希望以不可预测的顺序读取单个 int 元素,并且该算法不确定地运行(它正在进行中)。

// pseudo-code
while (true)
   UseInt(GetFileInt(GetRand(1<<40)));

我们在 Linux x86_64、gcc 上。您可以假设系统有 4GB 的 RAM(即比数据集少 1000 倍)

以下是架构访问的两种方式:

(A) 将文件 mmap 到 4TB 的内存块,并以 int 数组的形式访问

(B) 打开(2) 文件并使用 seek(2) 和 read(2) 读取整数。

在 A 和 B 中哪一个会有更好的性能?为什么?

是否有另一种设计可以提供比 A 或 B 更好的性能?

4

4 回答 4

3

一方面,您大量使用内存交换导致轻微的页面错误,对应用程序透明。另一方面,您有许多系统调用,具有已知的开销。关于内存映射文件的维基百科页面对我来说似乎很清楚,它以全面的方式浏览了优缺点。

我认为 64 位架构 + 大文件需要内存映射文件方法,至少可以避免应用程序复杂化;有人告诉我,复杂性通常会导致性能不佳。但是mmap()通常用于顺序访问,这不是这里的目的。

因为这是纯粹的随机访问,所以两次访问很少会出现在同一个 RAM 加载页面中。一个完整的 4kb 页面将从 HDD 交换到 RAM,仅用于 4 字节数据......这是无用的总线加载,可能会导致性能不佳。

希望这有帮助。

于 2012-06-14T11:54:56.880 回答
1

如果访问是真正随机的,我会说性能应该相似。操作系统将使用类似的缓存策略,无论数据页面是从文件映射还是文件数据只是缓存而不与 RAM 关联。

假设缓存无效:

  • 您可以使用fadvise提前声明您的访问模式并禁用预读。
  • 由于地址空间布局随机化,您的虚拟地址空间中可能没有 4 TB 的连续块。
  • 如果您的数据集不断扩展,地址空间问题可能会变得更加紧迫。

所以我会选择明确的阅读。

于 2012-06-14T12:51:19.030 回答
1

可能对于 4TB 线性数据集,您不需要文件系统。我猜原始设备访问可能会带来一些性能优势。

也可能有一种方法可以优化查询或数据结构,以便更有效地使用缓存?

于 2012-06-16T20:03:54.463 回答
1

寻求性能很大程度上取决于您的文件系统实现。Ext4 应该是一个不错的选择,因为它使用范围树。此外,如果您的文件具有线性连续分配,则范围树将由单个条目组成,这使得查找效率非常低。

于 2016-03-09T08:57:58.750 回答