当外部基础类型未按要求对齐时的atomic_ref [英] atomic_ref when external underlying type is not aligned as requested

查看:125
本文介绍了当外部基础类型未按要求对齐时的atomic_ref的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我阅读了 p0019r8 以下:

atomic_ref(T& obj);

要求:所引用的对象应与required_alignment对齐.

Requires: The referenced object shall be aligned to required_alignment.

cppreference 在未对齐时将其解释为UB:

cppreference interprets this as UB when not aligned:

如果obj未与required_alignment对齐,则行为未定义.

The behavior is undefined if obj is not aligned to required_alignment.


那么您希望实现如何处理?

并且实现可以检查编译时间 alignof,但是实际上类型可能比alignof更对齐.一个实现可以解释指针位并检查运行时对齐,但这是额外的运行时检查.

And implementation can check compile-time alignof, but in reality a type might be aligned more that alignof. An implementation can interpret pointer bits and check runtime alignment, but it is extra runtime check.

最终我看到以下选项:

  • 不执行任何操作-以不愉快的方式实现运行时未定义的行为,仅支持正确使用
  • 检查编译时对齐(alignof)并在出现错误时发出警告
  • 检查编译时对齐(alignof)并在编译时失败(如果错误)不正确,因为实际对齐可能大于静态类型可见的值
  • 检查编译时对齐(alignof)并在运行时因错误而失败不正确,因为实际对齐可能大于静态类型可见的值
  • 检查编译时对齐(alignof)并在错误的情况下回退到基于锁定的状态
  • 检查运行时对齐方式(指针位),如果出错则在运行时失败
  • 检查运行时对齐(指针位),并在错误的情况下回退到基于锁定的状态
  • Do nothing - implement runtime undefined behavior in unpleasant way, favor correct uses only
  • Check compile-time alignment (alignof) and emit warning if wrong
  • Check compile-time alignment (alignof) and fail at compile-time if wrong not correct since actual alignment may be greater than visible by static type
  • Check compile-time alignment (alignof) and fail at run-time if wrong not correct since actual alignment may be greater than visible by static type
  • Check compile-time alignment (alignof) and fallback to lock-based if wrong
  • Check run-time alignment (pointer bits) and fail at run-time if wrong
  • Check run-time alignment (pointer bits) and fallback to lock-based if wrong

推荐答案

TL:DR:从不默默地退回到锁定状态,没有人希望这样做,因为它破坏了std::atomic目的的主要部分. 将非锁定视为可移植性的替代,而不是可行的操作模式.

TL:DR: never silently fall back to locking, nobody ever wants that because it defeats a major part of the purpose of std::atomic. Think of non-lock-free as a portability fallback, not a viable mode of operation.

成为UB使得编译器合法可以简单地假设它,而无需检查它是否对齐. 一个UB概念的主要优点.这就是大多数人在优化的运行时对运行时的期望/期望,而不是使用可能会导致使用互斥锁的条件分支使代码膨胀.

Being UB makes it legal for the compiler to simply assume without any checking that it's aligned. Being able to assume without any runtime checks is one of the major benefits of the concept of UB. This is what most people want / expect at runtime in an optimized build, not bloating the code with conditional branches that might fall back to using a mutex.

在此处选择是否(以及如何)定义任何行为完全取决于实现,这取决于实施质量以及权衡性能与调试之间的关系.我想您知道这一点,并且实际上是在询问用户希望编译器为那些QoI选择选择什么,这很好.

The choice of whether (and how) to define any behaviour here is completely up to the implementation, as a matter of Quality-of-Implementation and trading off performance vs. debugging. I think you know that and are literally asking what users want compilers to pick for those QoI choices, which is fine.

正如您所链接的P0019提案所述,所有这些都归结为QOI问题:

As the P0019 proposal you linked says, it all comes down to a QOI issue:

  1. 参考能力约束

由原子引用引用的对象必须满足可能特定于体系结构的约束.例如,对象可能需要在内存中正确对齐,或者可能不被允许驻留在GPU寄存器内存中.我们不会列举所有潜在的约束,也不会在违反这些约束时指定行为. 在违反约束时生成适当的信息是实施质量问题.

An object referenced by an atomic reference must satisfy possibly architecture-specific constraints. For example, the object might need to be properly aligned in memory or might not be allowed to reside in GPU register memory. We do not enumerate all potential constraints or specify behavior when these constraints are violated. It is a quality-of-implementation issue to generate appropriate information when constraints are violated.

生成适当的信息"的措辞意味着他们期望实现在检测到违规时发出警告/错误,而不是回到锁定状态.

The "generate appropriate information" phrasing implies they expect implementations to warn / error if they detect a violation, not fall back to locking.

尽管可以退回到锁定 的实现可能会愚蠢地将required_alignment设置为最低的正确性(1),而不是最低的无锁性.当然,没有人希望这样做,但这是QoI问题,而不是标准遵从性.

Although an implementation that could fall back to locking could foolishly set required_alignment to the minimum for correctness (1), rather than the minimum for lock-freedom. Of course nobody wants that, but it's a QoI issue not standards-compliance.

我希望(或至少希望 )实现如下:

I'd expect (or at least hope) for an implementation to work as follows:

    如果在alignof小于required_alignment的任何对象上使用atomic_ref,则
  • 在编译时警告.您可能会知道,即使alignof(T)仅为1或4,某个T *p也会恰好是8字节对齐,因此这不应该是错误.

  • Warn at compile time if atomic_ref is used on any object whose alignof is less than required_alignment. You might know that a certain T *p happens to be 8 byte aligned even though alignof(T) is only 1 or 4, so this shouldn't be an error.

一些使警告消失的本地方法将是一件好事. (或者:用GNU C x = __builtin_assume_aligned(x, 16)保证与编译器对齐)

Some local way of silencing the warning would be a good thing. (Alternative: promise alignment to the compiler with something like GNU C x = __builtin_assume_aligned(x, 16))

至少警告在编译时是否确实已知未对齐对象,例如已知对齐方式的struct的子成员,或者声明可见但不包含alignas的全局var.通过可能可能未通过对齐的指针进行访问的警告嘈杂,应单独禁用.

At least warn if an object is definitely known to be under-aligned at compile time, e.g. a sub-member of struct whose alignment is known, or a global var where the declaration is visible but didn't include alignas. Warning for access through pointers that might be under-aligned is noisier and should be separately disable-able.

特慢调试模式:运行时检查对齐方式,针对原子性未对齐的特定对象发出警告或中止操作. (例如gcc -fsanitize=undefined或MSVC的调试模式,该调试模式已经添加了std::vector::operator[]边界检查之类的东西.我认为GCC的UBSan比MSVC调试模式执行更多的检查,例如用于签名溢出;我认为MSVC调试模式介于gcc -O0 -fsanitize=undefined.)

Extra-slow Debug mode: runtime check of alignment, warn or abort on a specific object being under-aligned for atomicity. (e.g. gcc -fsanitize=undefined, or MSVC's debug mode which already adds stuff like std::vector::operator[] bounds checks. I think GCC's UBSan does even more checking than MSVC debug mode, e.g. for signed overflow; I think MSVC debug mode is somewhere in between gcc -O0 and gcc -O0 -fsanitize=undefined.)

发布"模式:零检查,仅发出asm,其正确性取决于对齐的对象. (也有没有UBSan的gcc -O0,它允许进行一致的调试,但不添加额外的检查.)

"Release" mode: zero checking, just emit asm whose correctness depends on the object being aligned. (Also gcc -O0 without UBSan, which allows consistent debugging but doesn't add extra checks.)

没有人希望在编译时或运行时静默回退到互斥体.这种操作模式基本上就存在,因此ISO C ++可以要求该功能在任何地方都得到支持,而又不可能在某些目标上实现.

Nobody ever wants silent fallback to mutexes at compile time or run-time. That mode of operation basically just exists so ISO C++ can require the feature to be supported everywhere without making it impossible to implement on some targets.

与手动对关键部分进行细粒度锁定相比,锁定的后备通常不是最佳选择,关键部分在为其设计的数据结构上一次执行了一些相关的原子操作.人们使用atomic<T>(以及即将发布的atomic_ref<T>)来提高演奏性能,并且大部分演奏都会因锁定而被破坏.尤其是读取端可伸缩性.

The fallback to locking is usually very sub-optimal compared to manual fine-grained locking of a critical section that does a few related atomic ops at once on a data-structure designed for it. People use atomic<T> (and the upcoming atomic_ref<T>) for performance, and much of that performance is destroyed by locking. Especially read-side scalability.

脚注1:IIRC,alignof()仅为类型而不是对象指定,但在GNU C ++中,它也适用于对象.我将其用作编译器内部知识的简写,即某个对象使用alignas()对其进行了过度对齐.

Footnote 1: IIRC, alignof() is only specified for types, not objects, but in GNU C++ it also works on objects. I'm using this as shorthand for the compiler's internal knowledge that a certain object used alignas() to over-align it.

这篇关于当外部基础类型未按要求对齐时的atomic_ref的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆