热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

C++中的保持顺序的memcpy

如何解决《C++中的保持顺序的memcpy》经验,为你挑选了1个好方法。

我正在开发一个多核,多线程软件库,我想在其中提供可能跨越多个缓存行的更新顺序保留无锁共享内存对象.

具体来说,假设我有一些高速缓存行大小的对象的向量X:X [0],... X [K]每个占用恰好一个高速缓存行.我按索引顺序写入它们:首先是X [0],然后是X [1],等等.如果线程2读取X [K],它还会看到X [0]的状态是"至少是当前的"正如它看到的X [K]?

从同一个线程,显然我会看到尊重更新顺序的内存语义.但是现在如果某个第二个线程读取X [K]则会出现问题:是否会观察到对X [0] ...... X [K-1]的相应更新?

通过锁定,我们可以获得此保证.但是由于memcpy用于将某些东西复制到向量中,我们失去了这个属性:memcpy有一个POSIX语义,它不保证索引顺序更新或内存顺序更新或任何其他排序.您可以确保在memcpy完成后,已执行整个更新.

我的问题:是否已经有一个保持订单的memcpy具有相似的速度但具有所需的保证?如果没有,可以在没有锁定的情况下实现这样的原语吗?

假设我的目标平台是x86和ARM.

(编者注:最初称英特尔,所以OP可能不关心AMD.)



1> Peter Cordes..:

您描述的排序要求正是发布/获取语义所提供的.(http://preshing.com/20120913/acquire-and-release-semantics/).

问题是有效保证原子加载/存储的原子性单位在所有x86和某些ARM上最多为8个字节.否则只有4个字节在其他ARM上. (为什么在x86上对自然对齐的变量进行整数赋值?).一些英特尔CPU可能实际上拥有原子32甚至64字节(AVX512)存储,但英特尔和AMD都没有提供任何官方保证.

我们甚至不知道SIMD向量存储是否有保证顺序,因为它们可能会将宽对齐存储分成多个8字节对齐的块.或者即使这些块是单独的原子. 向量加载/存储和收集/分散的每元素原子性? 有充分的理由相信它们是按元素原子的,即使文档不能保证它.

如果拥有大型"对象"对性能至关重要,那么您可以考虑在您关心的特定服务器上测试向量加载/存储原子性,但是只要保证并让编译器使用它就完全靠您自己.(有内在函数.)确保在不同套接字的内核之间进行测试,以捕获SSE指令之类的情况:哪些CPU可以进行原子16B内存操作?由于K10 Opteron上的插座之间的HyperTransport,在8字节边界处撕裂.这可能是一个非常糟糕的主意; 你无法猜测,如果任何微架构条件在极少数情况下可以使宽矢量存储非原子,即使它通常看起来像是原子的.


您可以轻松地为数组元素发布/获取排序
alignas(64) atomic arr[1024];.
你只需要很好地询问编译器:

copy_to_atomic(std::atomic *__restrict dst_a, 
                      const uint64_t *__restrict src, size_t len) {
    const uint64_t *endsrc = src+len;
    while (src store( *src, std::memory_order_release );
        dst_a++; src++;
    }
}

在x86-64上它不会自动矢量化或任何东西,因为编译器不优化原子,并且因为没有文档可以安全地使用向量来存储原子元素数组的连续元素.:(所以这基本上很糟糕. 在Godbolt编译器浏览器上看到它

我会考虑使用volatile __m256i*指针(对齐的加载/存储)和编译器障碍atomic_thread_fence(std::memory_order_release)来阻止编译时重新排序.每个元素的排序/原子性应该没问题(但不能保证).并且绝对不要指望整个32字节是原子的,只是uint64_t在较低uint64_t元素之后写入更高的元素(并且那些存储按此顺序对其他核心可见).


在ARM32上:即使是a的原子存储uint64_t也不是很好.gcc使用ldrexd/ strexdpair(LL/SC),因为显然没有8字节的原子纯存储.(我使用gcc7.2 -O3 -march = armv7-a编译.在AArch32模式下使用armv8-a,存储对是原子的.当然,AArch64也有原子8字节加载/存储.)


您必须避免使用正常的C库memcpy实现. 在x86上,它可以使用弱排序的存储来存储大型副本,允许在它自己的存储之间进行重新排序(但不能用于以后不属于它的存储memcpy,因为这可能会破坏以后的发布存储.)

movnt高速缓存绕过存储在向量循环中,或rep movsb在具有ERMSB功能的CPU上,都可以创建此效果. 英特尔内存模型是否使SFENCE和LFENCE冗余?.

或者memcpy实现可以在进入其主循环之前首先选择最后(部分)向量.

atomic在C和C++中对UB中的非类型进行并发写+读或写+写; 这就是为什么memcpy有这么多自由做任何想做的事情,包括使用弱排序的存储,只要它sfence必要时使用以确保memcpy整体尊重编译器在为以后的mo_release操作发出代码时所期望的顺序.

(即x86的当前C++实现std::atomic假设没有弱排序的存储让他们担心.任何希望他们的NT存储尊重编译器生成的atomic代码的顺序的代码必须使用_mm_sfence().或者如果用手写asm ,sfence指令直接.或者只是使用,xchg如果你想做一个顺序发布商店,并给你的asm功能atomic_thread_fence(mo_seq_cst)也一样.)


关于_ordering_与_atomicity_,这个问题提出了有趣的观点.特别是,OP从不要求原子性:他要求保证当观察到后续存储(如`X [1]`)时,之前存储的位置(如`X [0]`)将至少为_最近_.我相信x86内存订购模型可以保证这一点,即使是宽SIMD加载和存储也是如此.也就是说,我的排序保证不应该(不是?)限制为原子访问.特别是,这似乎可以保证在"一次写入"的情况下,即使是广泛的商店......
推荐阅读
  • 基于PgpoolII的PostgreSQL集群安装与配置教程
    本文介绍了基于PgpoolII的PostgreSQL集群的安装与配置教程。Pgpool-II是一个位于PostgreSQL服务器和PostgreSQL数据库客户端之间的中间件,提供了连接池、复制、负载均衡、缓存、看门狗、限制链接等功能,可以用于搭建高可用的PostgreSQL集群。文章详细介绍了通过yum安装Pgpool-II的步骤,并提供了相关的官方参考地址。 ... [详细]
  • CentOS 7部署KVM虚拟化环境之一架构介绍
    本文介绍了CentOS 7部署KVM虚拟化环境的架构,详细解释了虚拟化技术的概念和原理,包括全虚拟化和半虚拟化。同时介绍了虚拟机的概念和虚拟化软件的作用。 ... [详细]
  • 本文概述了JNI的原理以及常用方法。JNI提供了一种Java字节码调用C/C++的解决方案,但引用类型不能直接在Native层使用,需要进行类型转化。多维数组(包括二维数组)都是引用类型,需要使用jobjectArray类型来存取其值。此外,由于Java支持函数重载,根据函数名无法找到对应的JNI函数,因此介绍了JNI函数签名信息的解决方案。 ... [详细]
  • 如何使用PLEX播放组播、抓取信号源以及设置路由器
    本文介绍了如何使用PLEX播放组播、抓取信号源以及设置路由器。通过使用xTeve软件和M3U源,用户可以在PLEX上实现直播功能,并且可以自动匹配EPG信息和定时录制节目。同时,本文还提供了从华为itv盒子提取组播地址的方法以及如何在ASUS固件路由器上设置IPTV。在使用PLEX之前,建议先使用VLC测试是否可以正常播放UDPXY转发的iptv流。最后,本文还介绍了docker版xTeve的设置方法。 ... [详细]
  • 【技术分享】一个 ELF 蠕虫分析
    【技术分享】一个 ELF 蠕虫分析 ... [详细]
  • 开发笔记:Squid代理服务
    本文由编程笔记#小编为大家整理,主要介绍了Squid代理服务相关的知识,希望对你有一定的参考价值。Squid服务基础缓存代理概述 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 开发笔记:计网局域网:NAT 是如何工作的?
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了计网-局域网:NAT是如何工作的?相关的知识,希望对你有一定的参考价值。 ... [详细]
  • Linux如何安装Mongodb的详细步骤和注意事项
    本文介绍了Linux如何安装Mongodb的详细步骤和注意事项,同时介绍了Mongodb的特点和优势。Mongodb是一个开源的数据库,适用于各种规模的企业和各类应用程序。它具有灵活的数据模式和高性能的数据读写操作,能够提高企业的敏捷性和可扩展性。文章还提供了Mongodb的下载安装包地址。 ... [详细]
  • 一句话解决高并发的核心原则
    本文介绍了解决高并发的核心原则,即将用户访问请求尽量往前推,避免访问CDN、静态服务器、动态服务器、数据库和存储,从而实现高性能、高并发、高可扩展的网站架构。同时提到了Google的成功案例,以及适用于千万级别PV站和亿级PV网站的架构层次。 ... [详细]
  • 嵌入式处理器的架构与内核发展历程
    本文主要介绍了嵌入式处理器的架构与内核发展历程,包括不同架构的指令集的变化,以及内核的流水线和结构。通过对ARM架构的分析,可以更好地理解嵌入式处理器的架构与内核的关系。 ... [详细]
  • 上图是InnoDB存储引擎的结构。1、缓冲池InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。因此可以看作是基于磁盘的数据库系统。在数据库系统中,由于CPU速度 ... [详细]
  • 微软评估和规划(MAP)的工具包介绍及应用实验手册
    本文介绍了微软评估和规划(MAP)的工具包,该工具包是一个无代理工具,旨在简化和精简通过网络范围内的自动发现和评估IT基础设施在多个方案规划进程。工具包支持库存和使用用于SQL Server和Windows Server迁移评估,以及评估服务器的信息最广泛使用微软的技术。此外,工具包还提供了服务器虚拟化方案,以帮助识别未被充分利用的资源和硬件需要成功巩固服务器使用微软的Hyper - V技术规格。 ... [详细]
  • 三、查看Linux版本查看系统版本信息的命令:lsb_release-a[root@localhost~]#lsb_release-aLSBVersion::co ... [详细]
  • 一、设置时区方法一:使用setup工具setup选择Timezoneconfiguration选择AsiaShanghai空格键勾选上System ... [详细]
author-avatar
75712533_6bdc45_141
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有