使用高速缓存行对齐,在C中修改全局共享状态的无锁检查

前端之家收集整理的这篇文章主要介绍了使用高速缓存行对齐,在C中修改全局共享状态的无锁检查前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
编辑:ST不允许为新手发布两个以上的链接.对不起,遗漏的参考.

我试图减少C应用程序中的锁定开销,其中检测全局状态的变化与性能相关.即使我最近一直在阅读这个话题(例如,来自H. Sutter等等),我对我的实现没有信心.我想使用CAS like操作和DCL的组合来对Cache-Line对齐的全局变量进行检查,从而避免虚假共享,从多个线程之间共享的数据更新线程本地数据.我缺乏信心主要是由于

>我没有在Type-Attributes解释GNU文档
>我似乎找不到任何可以很容易地转换为C的文献和例子,例如在ST或1上对齐到高速缓存行和知道高速缓存行大小(尽管1似乎是有些回答我的问题我对我的实现不信任)
>我对C的经验是有限的

我的问题:

>类型属性文档说明:

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 S或more_aligned_int的开始始终与8字节边界对齐?这并不意味着数据将被填充使用正好64字节,对吗?
>假设一个实例是struct cache_line_aligned(见下面的代码示例1)的每个实例都在64字节边界上对齐,并且恰好使用一条高速缓存行(假设高速缓存行长度为64字节)
>使用typedef作为类型声明不会改变__attribute__((aligned(64))的语义)(见下面的代码示例2)
>在实例化结构体时,我不需要使用aligned_malloc,如果struct用__attribute__声明…

// 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()等),就像上面的代码一样,它将对齐.

C标准(从1999年)指出malloc(),calloc()和realloc():

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).

如果任何类型的对象不包括像上述结构的人为对齐/填充类型,因为C标准中没有任何类似__attribute__((aligned(64))).这是这里的GNU扩展.对于具有任意对齐的动态分配对象,必须使用适当的内存分配功能或手动进行对齐(通过分配更多内存,然后“对齐”指针值).

猜你在找的C&C++相关文章