编辑: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中修改全局共享状态的无锁检查的更多相关文章

  1. ios – React native error – react-native-xcode.sh:line 45:react-native:command not found命令/ bin/sh失败,退出代码127

    尝试构建任何(新的或旧的)项目时出现此错误.我的节点是版本4.2.1,react-native是版本0.1.7.我看过其他有相同问题的人,所以我已经更新了本机的最新版本,但是我仍然无法通过xcode构建任何项目.解决方法要解决此问题,请使用以下步骤:>使用节点版本v4.2.1>cd进入[你的应用]/node_modules/react-native/packager>$sh./packager.s

  2. xcode – XCTest一个元组

    我正在尝试构建一个单元测试:但是Xcode给了我一个错误:无法使用类型的参数列表调用’XCTAssertEqual’是否有不同的方法来测试元组而不提取其成员并单独测试?解决方法XCTAssertEqual要求传递给它的两个参数是Equatable,您可以从方法签名中看到它们.注意,expression1返回T?,T必须是Equatable:但是Swifttuplesaren’tEquatable,所以你不能将它们与XCTAssertEqual一起使用.元组确实有一个==方法–它们只是不符合协议–所以你可以

  3. swift中方便调试的日志输出

    ///输出日志//////-parametermessage:日志消息///-parameterlogError:错误标记,默认是false,如果是true,发布时仍然会输出///-parameterfile:文件名///-parametermethod:方法名///-parameterline:代码行数funcprintLog{iflogError{print}else{#ifDEBUGprint#endif}}2.当发布的时候,如图讲-DDEBUG删除就可以了

  4. Swift中的打印日志的配置

    Swift中的打印日志的配置

  5. Swift日志打印

    publicfuncBMLog(message:T,file:String=FILE,method:String=FUNCTION,line:Int=LINE){#ifDEBUGprint(“((fileasNsstring).lastPathComponent)[line:(line)],(method):(message)”)#endif}

  6. Swift 下调试小技巧(备忘)iOS

    自定义log你是否经常出现print一大堆不知道那个是哪个?

  7. 将可选类型转换为错误抛出

    作者:EricaSadun,原文链接,原文日期:2016-10-07译者:wiilen;校对:Cee;定稿:CMBSoroushKhanlou曾写道:「很多时候我希望可选类型并不存在,“结果”就只是“结果”」。为延迟计算保留autoclosure。将全局函数放入类型中,使之称为静态成员。嵌套的错误声明。错误应能给你更多提示,而不是只显示一个名字。在声明了多行的复杂构造器之后使用Allman风格。

  8. NSLog有一个Swift替代(@“%s”,__PRETTY_FUNCTION__)

    虽然Swift不支持宏(我想),我仍然想使用一个通用的日志语句,包括被调用的函数的名称。__LINE__–Int–出现它的行号。__COLUMN__–Int–它开始的列号。__FUNCTION__–String–声明的名称。

  9. Swift中的宏?

    Swift目前是否支持宏,或者有未来计划要添加支持吗?在这种情况下,应为“宏”参数添加默认值。Swift2.2及更高版本Swift2.1和更低版本这是fatalError和assert函数做的。除了在另一个答案中已经提到的条件编译,没有其他宏。

  10. 在Swift中对齐vs步幅

    在Swift4中,MemoryLayout结构告诉您类型的大小,跨度和对齐方式.我理解大小和步幅,但不是真正的对齐.是否有一个示例显示了什么是对齐,它与步幅有什么不同,何时它与步幅有不同的值,以及使用步幅但使用对齐是否正确?我可以一直计算另一个吗?

随机推荐

  1. 从C到C#的zlib(如何将byte []转换为流并将流转换为byte [])

    我的任务是使用zlib解压缩数据包(已接收),然后使用算法从数据中生成图片好消息是我在C中有代码,但任务是在C#中完成C我正在尝试使用zlib.NET,但所有演示都有该代码进行解压缩(C#)我的问题:我不想在解压缩后保存文件,因为我必须使用C代码中显示的算法.如何将byte[]数组转换为类似于C#zlib代码中的流来解压缩数据然后如何将流转换回字节数组?

  2. 为什么C标准使用不确定的变量未定义?

    垃圾价值存储在哪里,为什么目的?解决方法由于效率原因,C选择不将变量初始化为某些自动值.为了初始化这些数据,必须添加指令.以下是一个例子:产生:虽然这段代码:产生:你可以看到,一个完整的额外的指令用来移动1到x.这对于嵌入式系统来说至关重要.

  3. 如何使用命名管道从c调用WCF方法?

    更新:通过协议here,我无法弄清楚未知的信封记录.我在网上找不到任何例子.原版的:我有以下WCF服务我输出添加5行,所以我知道服务器是否处理了请求与否.我有一个.NET客户端,我曾经测试这一切,一切正常工作预期.现在我想为这个做一个非托管的C客户端.我想出了如何得到管道的名称,并写信给它.我从here下载了协议我可以写信给管道,但我看不懂.每当我尝试读取它,我得到一个ERROR_broKEN_P

  4. “这”是否保证指向C中的对象的开始?

    我想使用fwrite将一个对象写入顺序文件.班级就像当我将一个对象写入文件时.我正在游荡,我可以使用fwrite(this,sizeof(int),2,fo)写入前两个整数.问题是:这是否保证指向对象数据的开始,即使对象的最开始可能存在虚拟表.所以上面的操作是安全的.解决方法这提供了对象的地址,这不一定是第一个成员的地址.唯一的例外是所谓的标准布局类型.从C11标准:(9.2/20)Apointe

  5. c – 编译单元之间共享的全局const对象

    当我声明并初始化一个const对象时.两个cpp文件包含此标头.和当我构建解决方案时,没有链接错误,你会得到什么如果g_Const是一个非const基本类型!PrintInUnit1()和PrintInUnit2()表明在两个编译单元中有两个独立的“g_Const”具有不同的地址,为什么?

  6. 什么是C名称查找在这里? (&amp;GCC对吗?)

    为什么在第三个变体找到func,但是在实例化的时候,原始变体中不合格查找找不到func?解决方法一般规则是,任何不在模板定义上下文中的内容只能通过ADL来获取.换句话说,正常的不合格查找仅在模板定义上下文中执行.因为在定义中间语句时没有声明func,并且func不在与ns::type相关联的命名空间中,所以代码形式不正确.

  7. c – 在输出参数中使用auto

    有没有办法在这种情况下使用auto关键字:当然,不可能知道什么类型的.因此,解决方案应该是以某种方式将它们合并为一个句子.这可用吗?解决方法看起来您希望默认初始化给定函数期望作为参数的类型的对象.您无法使用auto执行此操作,但您可以编写一个特征来提取函数所需的类型,然后使用它来声明您的变量:然后你就像这样使用它:当然,只要你重载函数,这一切都会失败.

  8. 在C中说“推动一切浮动”的确定性方式

    鉴于我更喜欢将程序中的数字保留为int或任何内容,那么使用这些数字的浮点数等效的任意算术最方便的方法是什么?说,我有我想写通过将转换放在解析的运算符树叶中,无需将表达式转化为混乱是否可以使用C风格的宏?应该用新的类和重载操作符完成吗?解决方法这是一个非常复杂的表达.更好地给它一个名字:现在当您使用整数参数调用它时,由于参数的类型为double,因此使用常规的算术转换将参数转换为double用C11lambda……

  9. objective-c – 如何获取未知大小的NSArray的第一个X元素?

    在objectiveC中,我有一个NSArray,我们称之为NSArray*largeArray,我想要获得一个新的NSArray*smallArray,只有第一个x对象…

  10. c – Setprecision是混乱

    我只是想问一下setprecision,因为我有点困惑.这里是代码:其中x=以下:方程的左边是x的值.1.105=1.10应为1.111.115=1.11应为1.121.125=1.12应为1.131.135=1.14是正确的1.145=1.15也正确但如果x是:2.115=2.12是正确的2.125=2.12应为2.13所以为什么在一定的价值是正确的,但有时是错误的?请启发我谢谢解决方法没有理由期望使用浮点系统可以正确地表示您的帖子中的任何常量.因此,一旦将它们存储在一个双变量中,那么你所拥有的确切的一

返回
顶部