返回介绍

4.1 连续存储

发布于 2024-01-25 22:02:55 字数 2280 浏览 0 评论 0 收藏 0

假设我们有一个4元素NumPy的字符串数组:

数学上这是一个2维对象。它有两个维度,可被一对取值范围为0到1的数索引:

然而,在计算机内存中可没有什么“两个维度”的说法,至少一般情况下没有。元素实际上被保存在一个1维缓存里:

这被称为连续存储,因为数组所有的元素,无论在磁盘还是内存,都是一个接一个存储的。NumPy使用一组简单规则将一个索引表达式转变为对这个1维缓存的偏移量。

在我们这个例子里,第一个维度上的索引会让我们在缓存上前进2步,第二个维度上的索引会让我们前进1步。

比如索引表达式a[0,1]被处理如下:

提示


 你可能已经注意到这里存在两种可能的转换:前进步数最快的索引可以是最后一个或第一个。这是行排序和列排序的区别。这里的例子中,Python、C以及HDF5都是行排序。

HDF5数据集默认都使用连续存储,除了最小的数据集空集。数据集里的数据被扁平地存入磁盘,这一点遵循NumPy(顺便提一下,还有C)使用的规则。

仔细想想,这意味着某些操作会比别的操作快很多。让我们考虑一个包含一百张640×480的灰阶图像的数据集,其形状为(100, 480, 640):

一个连续存储的数据集会将图像数据以具有640个元素的“扫描线”的形式一条条保存在磁盘上。如果我们读取第一张图像,切片的代码将会是:

图4-1(A)显示了其背后的工作原理。注意数据以640字节分块存储,和数据集最后一维的长度相符。当我们读取第一张图像时,我们从磁盘上读取了480个这样的块,全在一个大块里。

图4-1 磁盘上的连续存储,一次访问一整个图像(A),和一个64×64的图像区域(B)。灰色区域表示被读取的数据

这导致了我们处理磁盘数据的第一个原则(事实上也是唯一一个原则),位置原则如果数据被存储在一起,通常读起来更快。将数据组织在一起有很多理由,其中一个就是利用操作系统和HDF5自身的缓存。

很容易看到应用程序读取整个图像的效率非常高。连续存储的好处在于磁盘上的布局和数据集的形状直接相关:最后一维上索引向前进一步意味着磁盘上的数据向前进一步。

但如果我们不是要处理整个图像而只是一个图像区域呢?假设我们需要读取并处理第一张图像角落上一个64×64的像素块来添加一个标识。

我们的切片选择会是:

图4-1(B)显示了这种情况下数据是如何读取的。不怎么妙。我们的应用程序不得不从各地收集数据,而不是一次性读取一整块连续数据。如果我们想要一次性得到所有图像的64×64区块(dset[:,0:64,0:64]),我们要一路读到数据集的末尾!

这个问题最根本的原因在于默认的连续存储机制跟我们的访问模式不匹配。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文