存储 std::assume_aligned 指针 C++ 20
Posted
技术标签:
【中文标题】存储 std::assume_aligned 指针 C++ 20【英文标题】:Storing an std::assume_aligned pointer C++ 20 【发布时间】:2020-11-22 22:23:17 【问题描述】:在 C++ 20 中,我们假设对齐,这对于音频代码非常有用,其中指向对齐的浮点块的指针一直在传递。假设我们有以下跨度类型:
template<typename T>
struct Signal
const T* data
size_t size;
;
如何表明这个结构中的数据指针是由某个 constexpr 整数对齐的?在 C++ 20 中是否已经可以实现这样的功能?
constexpr int SIMDAlignment = 16;
template<typename T>
struct Signal
aligned<SIMDAlignment> const T* data
size_t size;
;
【问题讨论】:
【参考方案1】:似乎 assume-aligned 提示是特定指针对象的属性,不能成为指针类型的属性。但是,您可能会尝试通过(内联)getter 函数包装该指针,并使用std::assume_aligned
作为其返回值。例如,在我的实验中,当我使用这样一个函数返回的指针时,它被GCC正确地视为“对齐”(指向对齐的数据):
double* f()
static double* data =
(double*)std::aligned_alloc(64, 1024 * sizeof(double));
return std::assume_aligned<64>(data);
void g()
double* a = f();
for (int i = 0; i < 1024; i++)
a[i] = 123.45;
在这种情况下,数组由vmovapd
填充,这需要对齐的内存访问。
相反,当我改变时:
return std::assume_aligned<64>(data);
到:
return data;
生成的程序集包含vmovupd
,它适用于未对齐的数据。
现场演示:https://godbolt.org/z/d5aPPj — 检查两种情况下的 .L19
循环。
【讨论】:
这是有道理的,从名称来看,它只是 GNU Cvoid *__builtin_assume_aligned(void*, size_t)
的 std
版本也就不足为奇了。 gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html(在 C 中与 foo = __builtin_assume_aligned(foo, 64);
类似,允许与 void* 进行隐式转换。)
@PeterCordes 是的;甚至相应的提案也提到了__builtin_assume_aligned
为 GCC 和 Clang 提供的可能实现:open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1007r3.pdf。
在 GNU C 中,您有时可以执行 typedef int aligned_int __attribute__((aligned(16)))
之类的操作并拥有指向该类型的指针,但这是分开的。 (并且不那么容易工作,因为 sizeof(aligned_int) 也是 16,有填充)。 typedef 技巧更适合声明 under-aligned 和 may_alias
版本的类型。以上是关于存储 std::assume_aligned 指针 C++ 20的主要内容,如果未能解决你的问题,请参考以下文章