标签: memory-alignment

为什么GCC明确表示它会减慢程序时,会在O2/O3上启用优化?

引用自https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html:

-falign-标签

-falign-标签=正

将所有分支目标对齐为二次幂边界,跳过n个字节,如-falign-functions.此选项可以轻松地使代码变慢,因为它必须在通常的代码流中到达分支目标时插入虚拟操作.

-fno-align-labels和-falign-labels = 1是等效的,表示标签未对齐.

如果-falign-loops或-falign-jumps适用且大于此值,则使用它们的值.

如果未指定n或为零,则使用机器相关的默认值,该默认值很可能为"1",表示没有对齐.

在-O2,-O3级别启用.

考虑这个标志会使它失去更多的意义......有引发代码缓存未命中的后果,甚至启用意味着何时参数采用数值(1 ..)?

c++ gcc memory-alignment compiler-optimization

7
推荐指数
1
解决办法
185
查看次数

Default new alignment

I'm moving some C++17 code to be used in a project that is built with Qt, on Windows, using MinGW 7.3.0, and noticed something weird happening in the 32bit builds:

#include <cstddef>
#include <iostream>
int main() {
  std::cout << __STDCPP_DEFAULT_NEW_ALIGNMENT__ << std::endl;
  std::cout << __BIGGEST_ALIGNMENT__ << std::endl;
  std::cout << sizeof(std::max_align_t) << std::endl;
  std::cout << alignof(std::max_align_t) << std::endl;    
  std::cout << "----------------------------------------" << std::endl;    
  for (int i = 0; i < 8; ++i) {
    const uintptr_t        ptr   = uintptr_t(new char);
    static const …
Run Code Online (Sandbox Code Playgroud)

c++ default mingw memory-alignment new-operator

7
推荐指数
0
解决办法
89
查看次数

用C/C++解析二进制消息流

我正在为二进制协议(Javad GRIL协议)编写解码器.它由大约一百条消息组成,数据格式如下:

struct MsgData {
    uint8_t num;
    float x, y, z;
    uint8_t elevation;
    ...
};
Run Code Online (Sandbox Code Playgroud)

这些字段是ANSI编码的二进制数,它们彼此之间没有间隙.解析此类消息的最简单方法是将输入的字节数组转换为适当的类型.问题是流中的数据是打包的,即未对齐的.

在x86上,这可以通过使用来解决#pragma pack(1).但是,这在某些其他平台上不起作用,或者由于未对齐数据而导致性能开销.

另一种方法是为每种消息类型编写一个特定的解析函数,但正如我所提到的,该协议包含数百条消息.

另一种选择是使用类似Perl unpack()函数的东西并在某处存储消息格式.说,我们可以#define MsgDataFormat "CfffC"再打电话unpack(pMsgBody, MsgDataFormat).这要短得多,但仍然容易出错并且多余.此外,格式可能更复杂,因为消息可以包含数组,因此解析器将是缓慢而复杂的.

有没有共同有效的解决方案?我已经阅读了这篇文章,并用Google搜索,但没有找到更好的方法来做到这一点.

也许C++有一个解决方案?

c c++ binary parsing memory-alignment

6
推荐指数
2
解决办法
7848
查看次数

内部FLASH存储器中C结构的对齐

我有一个配置结构我想保存在ARM cortex M3的内部闪存上.根据规格,数据保存在内部闪存中,必须与32bit对齐.因为我有很多boolean和chars在我的结构中,我不想使用32位存储8位...我决定使用__packed预处理器编译指示打包结构,然后当我将它保存为整个结构时,我只需要确保结构大小可被4整除(4个字节= 32位),如果需要,我可以通过添加填充字节来实现.目前,在开发过程中我经常更改结构,并使其与32位对齐,我需要一直更改填充字节.目前,结构看起来很像

typedef __packed struct
{
uint8_t status;
uint16_t delay;
uint32_t blabla;
uint8_t foo[5];
uint8_t padding[...] // this has to be changed every time I alter the structure.
} CONFIG;
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法来实现我正在做的事情?我是嵌入式编程的新手,我想确保我没有犯错误.

编辑:请注意.数据在内部闪存结束时保留,因此省略填充将无法正常工作......

c cortex-m3 memory-alignment iar

6
推荐指数
2
解决办法
4402
查看次数

现代cpus如何处理跨页不对齐访问?

我试图理解未对齐的内存访问(UMA)如何在现代处理器(即x86-64和ARM体系结构)上工作.我知道我可能遇到UMA问题,从性能下降到CPU故障.我阅读posix_memalign并缓存行.

我找不到的是当我的请求超出页面边界时,现代系统/硬件如何处理这种情况?

这是一个例子:

  1. malloc()是一块8KB的内存.
  2. 假设malloc()没有足够的内存和sbrk()8KB的话.
  3. 内核获取两个内存页(每个4KB)并将它们映射到我的进程的虚拟地址空间(假设这两个页面在内存中不是一个接一个)
  4. movq (offset + $0xffc), %rax 我从第4092字节开始请求8个字节,这意味着我需要从第一页末尾开始的4个字节和从第二页开始开始的4个字节.

物理内存:

---|---------------|---------------|-->
   |... 4b|        |        |4b ...|-->
Run Code Online (Sandbox Code Playgroud)

我需要在页面边界分割的8个字节.

x86-64和ARM上的MMU如何处理这个问题?内核MM中是否有任何机制以某种方式为这种请求做准备?是否有某种保护malloc?处理器做什么?他们取两页吗?

我的意思是完成这样的请求MMU必须将一个虚拟地址转换为两个物理地址.它如何处理这样的请求?

如果我是软件程序员,我应该关心这些事情吗?为什么?

我正在阅读谷歌,SO,drepper的cpumemory.pdf和gorman的Linux VMM书中的很多链接.但它是一个信息的海洋.如果您至少向我提供一些我可以使用的指针或关键字,那将会很棒.

linux arm x86-64 memory-alignment mmu

6
推荐指数
1
解决办法
917
查看次数

动态分配正确对齐的内存:char 数组上的 new 表达式是否合适?

我遵循 Stefanus Du Toit 的沙漏模式,即在 C++ 中实现 C API,然后再次将其包装在 C++ 中。这与pimpl idiom非常相似,它对用户也是透明的,但可以防止更多与 ABI 相关的问题并允许更广泛的外语绑定。

与实现指针的方法一样,底层对象的大小和布局在编译时不被外界所知,因此它所在的内存必须动态分配(主要是)。然而,与pimpl情况不同,在pimpl情况下,对象已在分配点完全定义,这里它的属性完全隐藏在不透明指针后面。

获得的内存std::malloc是“适合任何标量类型”,这使得它不适合任务。我不确定new-expression。引自链接页面的分配部分:

此外,如果 new 表达式用于分配一个 char 数组或一个 unsigned char 数组,它可能会在必要时从分配函数中请求额外的内存,以保证不大于请求的数组大小的所有类型的对象的正确对齐,如果稍后将一个放入分配的数组中。

这是否意味着以下代码是合规的?

编程接口

size_t object_size      ( void );     // return sizeof(internal_object);
size_t object_alignment ( void );     // return alignof(internal_object);
void   object_construct ( void * p ); // new (p) internal_object();
void   object_destruct  ( void * p ); // …
Run Code Online (Sandbox Code Playgroud)

c++ memory-management memory-alignment

6
推荐指数
1
解决办法
1096
查看次数

我不明白在下面的代码中将char buffer []与X类型的对象对齐的原因

第151页的新书中的Stroustrup显示了以下使用类型说明符的示例alignas:

有时,我们必须在声明中使用对齐,其中不允许使用诸如alignof(x + y)之类的表达式.相反,我们可以使用类型说明符alignas:alignas(T)表示"就像T一样对齐" 例如,我们可以为某些类型X预留未初始化的存储,如下所示:

void user(const vector<X>& vx)
{
    constexpr int bufmax = 1024;
    alignas(X) char buffer[bufmax];    // unitialized
    const int max = min(vx.size(), bufmax/sizeof(X));
    unitialized_copy(vx.begin(), vx.begin() + max, buffer);
    ...
}
Run Code Online (Sandbox Code Playgroud)

c++ memory-alignment c++11

6
推荐指数
1
解决办法
139
查看次数

sizeof总是doubleof的倍数?

sizeof(Type)始终整除alignof(Type)

这样的陈述永远是真的吗? sizeof(Type) % alignof(Type) == 0

c++ sizeof memory-alignment

6
推荐指数
1
解决办法
192
查看次数

Eigen EIGEN_MAKE_ALIGNED_OPERATOR_NEW 的传递效果?

最近,我意识到的潜在问题内存对齐固定大小的矢量化的本征对象

文档所述的正确代码:

class Foo
{
  ...
  Eigen::Vector2d v;
  ...
public:
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};
 
...
 
Foo *foo = new Foo;
Run Code Online (Sandbox Code Playgroud)

我想知道这个代码是否可以?

class Foo2
{
  ...
  Foo foo;
  ...
};
 
...
 
Foo2 *foo = new Foo2; //?
Run Code Online (Sandbox Code Playgroud)

还是应该EIGEN_MAKE_ALIGNED_OPERATOR_NEWFoo2类中再次添加?这就是建议在这里我想:

如果我们添加 EIGEN_MAKE_ALIGNED_OPERATOR_NEW,这只能解决 Cartographer 库本身的问题。该库的用户还必须将 EIGEN_MAKE_ALIGNED_OPERATOR_NEW 添加到包含矢量化 Cartographer 类的类中。这听起来像是一场维护噩梦。

我没有新运算符重载的经验。我认为这个问题更笼统,并且以某种方式与 new 运算符在 C++ 中的工作方式有关。例如,重载的 new 运算符 inFoo是否被默认的 new 运算符 in 调用Foo2?继承呢?如果Foo2从继承Foo,要我们把同样EIGEN_MAKE_ALIGNED_OPERATOR_NEWFoo2? …

c++ memory-alignment new-operator eigen

6
推荐指数
1
解决办法
474
查看次数

使用 alignas 防止错误共享被破坏

我不习惯在互联网上发布任何问题,所以如果我做错了什么,请告诉我。

简而言之

  1. 如何在 CPU 缓存行大小为 64 字节的 64 位架构上正确防止错误共享?

  2. C++ 'alignas' 关键字和简单字节数组(例如:char[64])的使用如何影响多线程效率?

语境

在研究Single Consumer Single Producer Queue的非常有效的实现时,我在对我的代码进行基准测试时遇到了 GCC 编译器的不合逻辑行为。

全文

我希望有人有必要的知识来解释正在发生的事情。

我目前在 arch linux 上使用 GCC 10.2.0 及其 C++ 20 实现。我的笔记本电脑是带有 i7-7500U 处理器的联想 T470S。

让我从数据结构开始:

class SPSCQueue
{
public:
    ...

private:
    alignas(64) std::atomic<size_t> _tail { 0 }; // Tail accessed by both producer and consumer
    Buffer _buffer {}; // Buffer cache for the producer, equivalent to _buffer2
    std::size_t _headCache { 0 }; // Head cache for the …
Run Code Online (Sandbox Code Playgroud)

c++ multithreading x86-64 memory-alignment false-sharing

6
推荐指数
1
解决办法
343
查看次数