【问题标题】:C code for alignment on Intel Core 2 Duo在 Intel Core 2 Duo 上对齐的 C 代码
【发布时间】:2015-07-01 13:29:35
【问题描述】:

我得到了以下用于对齐的 c 代码

struct s *p, *new_p
p = (struct s*) malloc(sizeof(struct s) + BOUND -1);
new_p = (struct s*) (((int) p+BOUND-1) & ~(BOUND -1);

其中 BOUND 表示 32 个字节。一行高速缓存像 Pentium II 和 III 一样是 32 字节,但我无法弄清楚 p 和 new_p 对齐的方式。都对齐还是只有 new_p?

另外,我有一个 64 B 的缓存行代码,用于一组关联缓存,每组有 8 个块,大小为 32 Kb:

int *tempA, *tempB;
...
pA= (int *) malloc (sizeof(int)*N + 63);
tempA = (int *)(((int)pA+63)&~(63));
tempB = (int *)((((int)pA+63)&~(63))+4096+64)

附上这句话:如果你访问超过 8 个地址,间隔为 4 Kb,将会受到惩罚。

整个对我来说没有多大意义。有什么想法吗?

【问题讨论】:

    标签: c caching memory-alignment


    【解决方案1】:

    为什么不使用_Alignas()(C11 起)?

    将指针指向int 会招致灾难(又名未定义的行为)。想想一个 32 位的 64 位机器(大多数 x86 的标准)。 如果您需要对指针进行算术运算,请使用uintptr_t(不过我不建议使用intptr_t)。然而,即使在这里,值的算术仍然是未定义的(但对于具有单一线性地址空间的平台来说很可能是安全的)。

    标准说明:notvoid * 转换为malloc() 返回的内容。

    更新:

    好的,让我们把上面的代码给它一个正确的格式和类型:

    #include <stdint.h>
    
    // align to this boundary (must be power of two!)
    #define ALIGN_BOUNDARY 64U
    

    不要在代码中使用幻数! 2 个月后,您会想知道这意味着什么。

    int *tempA, *tempB;
    

    这些是如何使用的?

    int *pA = malloc (sizeof(int) * N + ALIGN_BOUNDARY - 1);
    uintptr_t adjA = ((uintptr_t)pA + (ALIGN_BOUNDARY - 1)) & ~((uintptr_t) (ALIGN_BOUNDARY - 1);
    

    这只是将地址四舍五入到下一个对齐的边界(这里:64 字节)。

    tempA = (int *)adjA;
    tempB = (int *)(adjA + 4096 + 64)
    

    不确定后者有什么用处,但是在给定 malloc 的情况下,如果使用与 *pA 相同的索引 (0..N) 访问超出分配的块,这将导致灾难.

    无论如何,我都会非常非常小心地处理这段代码。不仅它显然写得不好/记录不好,而且似乎也包含错误。

    【讨论】:

    • 请注意,这个问题更多地与当前代码的作用有关,在找到替代方法之前您需要知道这些。
    • @nos:我认为中间(也是最大的)部分实际上是相关的。但是,如果您坚持,我可以交换段落。
    • Olaf 我觉得你的回答很有趣,但仍然不太了解第二个代码及其备注...
    • @Rodrigo:如果您的代码在 64 位平台上运行,则该代码可能无法工作,因为 int 太短而无法容纳指针(启用编译器警告!)。即使,我至少会怀疑,因为它显然没有很好地设计所有的幻数等。但是,我将解释基础知识。
    • @Rodrigo:我编辑了我的答案。请注意,这可能不是一个正确的答案,但是对于评论来说太长并且需要结构化代码,所以..
    猜你喜欢
    • 1970-01-01
    • 2013-08-14
    • 2010-10-09
    • 1970-01-01
    • 2011-05-07
    • 1970-01-01
    • 2015-11-27
    • 1970-01-01
    • 2016-06-21
    相关资源
    最近更新 更多