手动填充数组

Padding array manually

我想从this book理解9点模板的算法,逻辑对我来说很清楚,但是WIDTHP宏的计算是我无法理解的,这里是breif代码(原始代码超过 300 行长度!!):

#define PAD64 0
#define WIDTH 5900
#if PAD64
#define WIDTHP ((((WIDTH*sizeof(REAL))+63)/64)*(64/sizeof(REAL)))
#else
#define WIDTHP WIDTH
#endif
#define HEIGHT 10000

REAL *fa = (REAL *)malloc(sizeof(REAL)*WIDTHP*HEIGHT);
REAL *fb = (REAL *)malloc(sizeof(REAL)*WIDTHP*HEIGHT);

原始数组是 5900 X 10000,但如果我定义 PAD64,数组 变成 5915.75 X 10000

虽然到目前为止我可以猜测作者正在尝试将数组对齐并填充到 64 字节边界。但是 malloc 返回的数组通常是 aligned(& padded) ,另外, posix_memalign gives you a chunk of memory that is guaranteed to have the requested alignment ,我们也可以使用

__attribute__((align(64)))

此 WIDTHP 会对我的代码性能产生什么影响?

想法是矩阵的每一行(或列,如果它被视为列主矩阵)可以通过在行的末尾添加填充来与新缓存行的开头对齐。这究竟有什么影响当然在很大程度上取决于访问模式,但一般来说,缓存友好性对于密集的数字运算代码非常重要。

另外,计算的是整数,所以结果肯定不是5915.75,这没有意义。

宽度p的计算方式是

( Width/64) +1

全面的整数精度数学。我会给你一个更好的答案,除了在 SE 移动应用程序中,无法在这个和列表之间滑动

我打算把它作为对 unwind 的回答的评论,因为他是对的。但也许我可以解释得更清楚,尽管字符数多于评论中的字符数。

当我计算时,我得到 5904 实数,即 23616 字节,对于 64 字节缓存行来说,这是 396 个缓存行。它是字节,而不是元素的数量,必须是 64 的倍数。

至于为什么要填充宽度的值,让我们看一个较小的例子。假设我们有一个包含 10 个字母的 "cache line" 并且我们有一个宽度为 8 个字母且高度为 4 的 "array"。现在由于我们假设的数组在 C 中并且 C 是主要行,因此数组看起来像这样: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD

但是当它排列在缓存行中时它看起来像什么,因为它们有 10 个字母长: AAAAAAAABB BBBBBBCCCC CCCCDDDDDD DD

不好。只有数组的第一行对齐。但是如果我们用两个空格填充宽度,我们会在缓存中得到这个: AAAAAAAA__ BBBBBBBB__ CCCCCCCC__ DDDDDDDD__

这就是我们想要的。现在我们可以有一个像

这样的嵌套循环
for i = 1 to height
   for j = 1 to width

并且知道每次我们开始处理 j 循环时,我们需要的数据都会对齐。

哦,是的,他们确实应该做些事情来确保数组的第一个元素对齐。 'attribute((align(64)))' 将不起作用,因为数组是动态分配的,但它们可以使用 posix_memalign 而不是 malloc。