gpt4 book ai didi

c - 使用 Cache-Line 对齐对 C 中全局共享状态的修改进行无锁检查

转载 作者:IT王子 更新时间:2023-10-28 23:33:32 27 4
gpt4 key购买 nike

编辑:ST 不允许为新手发布两个以上的链接。很抱歉缺少引用资料。

我正在尝试减少 C 应用程序中的锁定开销,其中检测全局状态的更改与性能相关。尽管我最近读了很多关于这个主题的书(例如很多来自 H. Sutter 的书,等等),但我对自己的实现没有信心。我想使用类似 CAS 的操作和 DCL 的组合来检查 Cache-Line Aligned 全局变量,从而避免错误-sharing,从多个线程之间共享的数据中更新线程本地数据。我缺乏信心主要是因为

  1. 我未能解释 Type-Attributes 上的 GNU 文档
  2. 我似乎找不到任何可以轻松翻译成 C 语言的文献和示例,例如 aligning-to-cache-line-and-knowing-the-cache-line-size在 ST 或 1 (虽然 1 似乎在某种程度上回答了我的问题,但我对我的实现没有信心)
  3. 我的 C 语言经验有限

我的问题:

  1. Type-Attributes 文档指出:

    This attribute specifies a minimum alignment (in bytes) for variables of the specified type. For example, the declarations:

    (please see Type-Attributes documentation for declaration)

    force the compiler to insure (as far as it can) that each variable whose type is struct S or more_aligned_int will be allocated and aligned at least on a 8-byte boundary. On a SPARC, having all variables of type struct S aligned to 8-byte boundaries allows the compiler to use the ldd and std (doubleword load and store) instructions when copying one variable of type struct S to another, thus improving run-time efficiency.

    这是否意味着 struct Smore_aligned_int 的开头将始终与 8-byte 边界对齐?这并不意味着数据将被填充为正好使用 64 个字节,对吧?

  2. 假设 1. struct cache_line_aligned 的每个实例(参见下面的代码 示例 1)都在 64 字节 上对齐,这是真的边界并仅使用一个缓存行(假设缓存行的长度为 64 字节)

  3. 使用 typedef 进行类型声明不会改变 __attribute__ ((aligned (64))) 的语义(参见代码 示例 2 下面)

  4. 如果使用 __attribute__ ...

  5. 声明结构,则在实例化结构时不需要使用 aligned_malloc
// Example 1
struct cache_line_aligned {
 int version;
 char padding[60];
} __attribute__ ((aligned (64)));

// Example 2
typedef struct {
 int version;
// place '__attribute__ ((aligned (64)))' after 'int version'
// or at the end of the declaration
 char padding[60];
} cache_line_aligned2 __attribute__ ((aligned (64)));

最后是一个函数的草图,它使用缓存行对齐的方法来有效地检查全局状态是否已被其他线程修改:

void lazy_update_if_changed(int &t_version, char *t_data) {
// Assuming 'g_cache_line_aligned' is an instance of
// 'struct cache_line_aligned' or 'struct cache_line_aligned2'
// and variables prefixed with 't_' being thread local
if(g_cache_line_aligned.version == t_version) {
// do nothing and return
} else {
// enter critical section (acquire lock e.g. with pthread_mutex_lock)
t_version = g_cache_line_aligned.version
// read other data that requires locking where changes are notified
// by modifying 'g_cache_line_aligned.version', e.g. t_data
// leave critical section
}
}

抱歉,帖子太长了。

谢谢!

最佳答案

当您定义对齐类型时,例如,对齐到 8 字节边界,编译器应通过填充使该类型的大小成为对齐的倍数(此处为 8 字节的倍数)。

这样做的理由很简单。假设您要定义该对齐类型的数组。自然,它的每个元素也应该对齐。这就是为什么可能会有填充。

这里有一个小示范:

#include <stdio.h>

struct cache_line_aligned {
int version;
// char padding[60];
} __attribute__ ((aligned (64)));

int main(void)
{
struct cache_line_aligned s;
struct cache_line_aligned a[2];
printf("sizeof(struct cache_line_aligned) = %d\n", (int)sizeof(struct cache_line_aligned));
printf("sizeof(s) = %d\n", (int)sizeof(s));
printf("sizeof(a[0]) = %d\n", (int)sizeof(a[0]));
printf("sizeof(a) = %d\n", (int)sizeof(a));
return 0;
}

输出(ideone):

sizeof(struct cache_line_aligned) = 64
sizeof(s) = 64
sizeof(a[0]) = 64
sizeof(a) = 128

如果你非动态地创建一个 struct cache_line_aligned 实例(IOW,而不是通过 malloc() 等),就像上面的代码一样,它将是对齐。

malloc()calloc()realloc() 的 C 标准(从 1999 年开始):

The pointer returned if the allocation succeeds is suitably aligned so that
it may be assigned to a pointer to any type of object and then used to
access such an object or an array of such objects in the space allocated
(until the space is explicitly deallocated).

any type of object 不包括像上面的结构那样人为对齐/填充的类型,因为没有像 __attribute__ ((aligned (64)))这样的东西在 C 标准中。这是这里的 GNU 扩展。对于具有任意对齐方式的动态分配对象,您必须使用适当的内存分配函数或手动进行对齐(通过分配更多内存然后“对齐”指针值)。

关于c - 使用 Cache-Line 对齐对 C 中全局共享状态的修改进行无锁检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12592342/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com