2

我试图从这本书中理解 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 返回的数组通常是对齐的(&填充),另外,posix_memalign 给你一块保证有请求对齐的内存,我们也可以使用

__attribute__((align(64)))

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

4

3 回答 3

3

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

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

于 2015-04-30T08:43:29.383 回答
2

我打算把这个作为评论来放松的回答,因为他是对的。但也许我可以更清楚地解释,尽管字符多于评论。

当我进行数学运算时,我得到 5904 实数,即 23616 字节,对于 64 字节缓存线,这是 396 条缓存线。它是字节,而不是元素的数量,它必须是 64 的倍数。

至于为什么要填充宽度的值,让我们看一个更小的例子。假设我们有一个包含 10 个字母的“缓存行”,并且我们有一个宽度为 8 个字母、高度为 4 的“数组”。现在,由于我们假设的数组是 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。

于 2015-05-01T02:36:25.503 回答
-1

宽度 p 计算是说

( Width/64) +1

对于 int 精度数学,四舍五入。我会给你一个更好的答案,除了在 SE 移动应用程序中,在这个和列表之间滑动是不可行的

于 2015-04-30T08:45:35.523 回答