根据 OpenMP 规范 (v4.0),由于 i 的不同步读/写,以下程序包含可能的数据竞争:
int i{0}; // std::atomic<int> i{0};
void write() {
// #pragma omp atomic write // seq_cst
i = 1;
}
int read() {
int j;
// #pragma omp atomic read // seq_cst
j = i;
return j;
}
int main() {
#pragma omp parallel
{ /* code that calls both write() and read() */ }
}
我想到的可能的解决方案在代码中显示为注释:
i的读写与 #pragma omp atomic write/read ,i的读写与 #pragma omp atomic write/read seq_cst ,std::atomic<int>而不是 int作为 i 的一种.这是编译器在 x86_64 上生成的指令(在所有情况下都是 -O2):
GNU g++ 4.9.2: i = 1; j = i;
original code: MOV MOV
#pragma omp atomic: MOV MOV
// #pragma omp atomic seq_cst: MOV MOV
#pragma omp atomic seq_cst: MOV+MFENCE MOV (see UPDATE)
std::atomic<int>: MOV+MFENCE MOV
clang++ 3.5.0: i = 1; j = i;
original code: MOV MOV
#pragma omp atomic: MOV MOV
#pragma omp atomic seq_cst: MOV MOV
std::atomic<int>: XCHG MOV
Intel icpc 16.0.1: i = 1; j = i;
original code: MOV MOV
#pragma omp atomic: * *
#pragma omp atomic seq_cst: * *
std::atomic<int>: XCHG MOV
* Multiple instructions with calls to __kmpc_atomic_xxx functions.
我想知道为什么 GNU/clang 编译器不为 #pragma omp atomic 生成任何特殊指令写。我期望与 std::atomic 类似的说明,即 MOV+MFENCE或 XCHG .有什么解释吗?
更新
g++ 5.3.0 生成 MFENCE对于 #pragma omp atomic write seq_cst .我相信这是正确的行为。没有 seq_cst , 它产生普通的 MOV , 这对于非 SC 原子性是足够的。
我的 Makefile 中有一个错误,g++ 4.9.2 生成 MFENCE也适用于 CS 原子写入。对不起大家。
Clang 3.5.0 未实现 OpenMP SC 原子,感谢 Hristo Iliev 指出这一点。
最佳答案
有两种可能。
编译器没有义务将包含数据竞争的 C++ 代码转换为错误的机器代码。根据机器内存模型,通常使用的指令可能已经是原子的和连贯的。将相同的 C++ 代码用于另一个架构,您可能会开始看到 pragma 导致 x86_64 上不存在的差异。
除了可能导致使用不同的指令和/或额外的内存栅栏指令之外,原子编译指示(以及 std::atomic 和 volatile)还限制了编译器自己的代码重新排序优化。它们可能不适用于您的简单情况,但您肯定会看到公共(public)子表达式消除(包括循环外的提升计算)可能会受到影响。
关于c++ - OpenMP 原子和非原子读/写在 x86_64 上产生相同的指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35462453/
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
让多条路线去同一条路的最优雅的方式是什么ControllerAction?我有:get'dashboard',to:'dashboard#index'get'dashboard/pending',to:'dashboard#index'get'dashboard/live',to:'dashboard#index'get'dashboard/sold',to:'dashboard#index'这很丑陋。有什么“更优雅”的建议吗?一个类轮的奖励积分。 最佳答案 为什么不只有一个路由和一个Controller操作,并根据传递给它的参数来
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我
我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“
在我的路线文件中我有:match'graphs/(:id(/:action))'=>'graphs#(:action)'如果是GET请求(工作)或POST请求(不工作),我想匹配它我知道我可以使用以下方法在资源中声明POST请求:post'/'=>:show,:on=>:member但是我怎样才能为比赛做到这一点呢?谢谢。 最佳答案 如果你同时想要POST和GETmatch'graphs/(:id(/:action))'=>'graphs#(:action)',:via=>[:get,:post]编辑默认值可以设置如下match'g