C++20中存储std::assume_aligned指针

3
在C++20中,我们获得了“assume aligned”功能,在音频代码中传递指向对齐的浮点数块的指针时非常有用。假设我们有以下跨度类型:
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个回答

3

看起来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 循环。

1
这很有道理,从名称上看,它只是GNU C void *__builtin_assume_aligned(void*, size_t)std版本,这并不令人惊讶。https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html(在C中使用类似于`foo = __builtin_assume_aligned(foo, 64);`,其中允许隐式转换为/从void*。) - Peter Cordes
@PeterCordes 是的;甚至相应的提案中提到了GCC和Clang可能通过__builtin_assume_aligned进行实现:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1007r3.pdf。 - Daniel Langr
在GNU C中,有时候你可以做一些像typedef int aligned_int __attribute__((aligned(16)))这样的事情,并且有指向该类型的指针,但那是分开的。(而且不太容易工作,因为sizeof(aligned_int)也是16,带填充)。typedef技巧更适用于声明*未对齐和may_alias版本的类型。 - Peter Cordes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接