草庐IT

c++ - MS 特定的 volatile 是否会阻止硬件指令重新排序

coder 2024-02-10 原文

来自documentation :

Microsoft Specific

When the /volatile:ms compiler option is used—by default when architectures other than ARM are targeted—the compiler generates extra code to maintain ordering among references to volatile objects in addition to maintaining ordering to references to other global objects.In particular:

  • A write to a volatile object (also known as volatile write) has Release semantics; that is, a reference to a global or static object
    that occurs before a write to a volatile object in the instruction
    sequence will occur before that volatile write in the compiled
    binary.
  • A read of a volatile object (also known as volatile read) has Acquire semantics; that is, a reference to a global or static object
    that occurs after a read of volatile memory in the instruction
    sequence will occur after that volatile read in the compiled binary.

This enables volatile objects to be used for memory locks and releases in multithreaded applications.

它肯定保证 volatile 阻止编译器进行编译时指令重新排序(因为它明确声明指令 序列将与在编译后的二进制文件中)相同。

但众所周知,还有硬件重排序之类的东西(比如 CPU 能够按照自己的意愿对指令进行重排序)。 volatile 是否也能阻止它?我知道同步原语(例如互斥锁)可以,但是 MS 特定的 volatile 呢?

最佳答案

有关 MS 特定 volatile 行为的 MSDN 文档一直追溯到 VS2003。所以它已经存在了一段时间——远早于 C++11 中 std::atomic 的存在。

因此,MS 特定的 volatile 似乎是过去实现获取/释放语义的方式。但现在它基本上已经过时了,他们留下了一个脚注,让您远离 MS-volatile,转而使用 std::atomic/volatile:iso 进行线程间通信。


至于他们为什么将 ARM 排除在外,Microsoft 直到最近才选择 ARM。除了 ARM,它们还支持 x86、x64 和 Itanium(已死)。

在 x86 和 x64 上,大多数加载和存储已经具有获取/释放语义(非临时存储等异常(exception))。因此,只要编译器不重新排序任何东西,处理器就不会*,因此会保留获取/释放语义。 /volatile:ms 标志告诉编译器不要重新排序任何东西,以便可以在 x86 和 x64 上实现获取/释放语义。

由于 Microsoft 的 ARM 支持相对较新,并且 MS 特定的 volatile (/volatile:ms) 已过时,取而代之的是 std::atomic,他们可能决定放弃经典的 volatile 语义而不是更新它们以在 ARM 上工作(这可能意味着在缺乏硬件支持的情况下到处添加内存屏障)。

*处理器仍将执行它想要的任何重新排序,但它将保留程序的获取/释放语义,因为这是 x86/x64 所要求的。 (减去 nt-stores 或 clflush 等异常(exception)情况)它如何在不违反内存顺序的情况下做到这一点是另一个主题。

关于c++ - MS 特定的 volatile 是否会阻止硬件指令重新排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38903753/

有关c++ - MS 特定的 volatile 是否会阻止硬件指令重新排序的更多相关文章

  1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  2. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  3. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  4. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  5. ruby - 检查数组是否在增加 - 2

    这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife

  6. ruby-on-rails - active_admin 目录中的常量警告重新声明 - 2

    我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA

  7. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

  8. ruby-on-rails - Ruby 检查日期时间是否为 iso8601 并保存 - 2

    我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby​​是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查

  9. ruby - 检查日期是否在过去 7 天内 - 2

    我的日期格式如下:"%d-%m-%Y"(例如,今天的日期为07-09-2015),我想看看是不是在过去的七天内。谁能推荐一种方法? 最佳答案 你可以这样做:require"date"Date.today-7 关于ruby-检查日期是否在过去7天内,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/32438063/

  10. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

随机推荐