标签: memory-alignment

跨平台ALIGN(x)宏?

我想创建一个struct具有一定对齐的.

我想对GCC和VisualC++编译器使用相同的结构定义.

在VisualC++中,通常会这样做:

__declspec(align(32))
struct MyStruct
{
// ...
};
Run Code Online (Sandbox Code Playgroud)

在GCC中,通常会这样做:

struct MyStruct
{
// ...
} __attribute__ ((aligned (32)));
Run Code Online (Sandbox Code Playgroud)

我当然可以创建适当的宏来使其工作:

BEGIN_ALIGNED_STRUCT(32)
struct
{
// ...
}
END_ALIGNED_STRUCT(32)
;
Run Code Online (Sandbox Code Playgroud)

因此能够透明地处理这两种情况,但在这里我必须复制对齐常量(32),我想避免.

在GCC另一种方法是把__attribute__结构体标签后,作为中提到的文档,就像这样:

struct __attribute__ ((aligned (32))) MyStruct
{
// ...
};
Run Code Online (Sandbox Code Playgroud)

因此我可以使这种类型的语法工作:

ALIGNED_STRUCT(32) MyStruct
{
// ...
};
Run Code Online (Sandbox Code Playgroud)

有没有人有更好的版本?其他想法?我尝试了一些代码搜索,但没有找到任何有希望的东西.


更新:基于@John的评论,这是另一个可以工作的版本(我没有编译它,但文档表明这是一个好主意)

struct MyStruct_Unaligned
{
// ...
};

TYPEDEF_ALIGNED(32, MyStruct_Unaligned, MyStruct);

// Would expand to one of:
// 
// typedef __declspec(align(32)) MyStruct_Unaligned MyStruct;
// …
Run Code Online (Sandbox Code Playgroud)

g++ memory-alignment visual-c++

17
推荐指数
2
解决办法
1万
查看次数

是否有GCC关键字允许结构重新排序?

我知道为什么GCC默认不重新排序结构的成员,但我很少编写依赖于结构顺序的代码,所以有什么方法可以标记我的结构自动重新排序?

c gcc c99 padding memory-alignment

17
推荐指数
2
解决办法
2393
查看次数

Java内存分配对齐

我知道在Java中这是一个奇怪的问题,但有没有办法让Java动态内存分配与一些对齐约束对齐?例如,是否可以动态分配与页面大小对齐的对象?

我想这样做的原因是因为我将通过JNI接口从本机代码访问Java对象,而本机代码库需要对齐对象.

谢谢.

java memory-management memory-alignment

16
推荐指数
2
解决办法
5366
查看次数

为什么C中的双精度是8字节对齐?

我正在阅读一篇关于内存中数据类型对齐的文章(这里),我无法理解一点,即

请注意,双变量将在32位机器上的8字节边界上分配,并且需要两个存储器读取周期.在64位机器上,根据存储体的数量,双变量将在8字节边界上分配,并且只需要一个存储器读周期.

我的疑问是:为什么需要在8字节边界上分配双变量而不是4字节?如果它仍然分配在4字节边界上,我们只需要2个存储器读周期(在32位机器上).如果我错了,请纠正我.

如果有人有一个关于成员/内存对齐的好教程,请分享.

c memory-alignment 32bit-64bit

16
推荐指数
1
解决办法
6284
查看次数

如何捕获未对齐的内存访问?

我正在开发一个宠物开源项目,它实现了一些流密码算法,我遇到的问题只有在我在ARM处理器上运行时才会触发.我甚至尝试在qemu下运行x86中的ARM二进制文件,但是那里没有触发bug.

这个bug的具体机制仍然是难以捉摸的,但我最好的办法是相信它是由我的程序中未对齐的内存访问尝试引起的,这是由qemu实现的,但是我的开发板中真正的ARM处理器默默地忽略了它.

因此,由于问题显示非常难以诊断,我想知道是否有任何工具可用于捕获我运行的程序所做的未对齐内存访问,以便我可以确切地看到问题发生的位置.

我还可以使用某种方式在我的ARM开发板上启用一些信号(SIGBUS,可能?),如果进程违反了内存对齐限制,就像我们在访问未映射的内存地址时得到SIGSEGV一样.它运行的是Linux 2.6.32.

c linux arm memory-alignment

16
推荐指数
2
解决办法
1万
查看次数

在字对齐处理器上使用未对齐数据的最快方法?

我正在ARM Cortex M0上做一个项目,它不支持未对齐(4字节)访问,我正在尝试优化未对齐数据的操作速度.

我将蓝牙低功耗访问地址(48位)作为6字节数组存储在一些作为数据包缓冲区的打包结构中.由于打包,BLE地址不一定从字对齐的地址开始,并且在优化我对这些地址的访问功能时遇到了一些复杂问题.

第一种也是最明显的方法是对数组中每个字节单独运行的for循环.例如,检查两个地址是否相同可以这样做:

uint8_t ble_adv_addr_is_equal(uint8_t* addr1, uint8_t* addr2)
{
  for (uint32_t i = 0; i < 6; ++i)
  {
    if (addr1[i] != addr2[i])
      return 0;
  }
  return 1;
}
Run Code Online (Sandbox Code Playgroud)

我在我的项目中做了很多比较,我想看看是否可以从这个功能中挤出更多的速度.我意识到对于对齐的地址,我可以将它们转换为uint64_t,并与应用的48位掩码进行比较,即

((uint64_t)&addr1[0] & 0xFFFFFFFFFFFF) == ((uint64_t)&addr2[0] & 0xFFFFFFFFFFFF)
Run Code Online (Sandbox Code Playgroud)

可以对写入进行类似的操作,并且它适用于对齐版本.但是,由于我的地址并不总是字对齐(甚至是半字),所以我必须做一些额外的技巧来完成这项工作.

首先,我想出了编译器宏的未经优化的噩梦:

#define ADDR_ALIGNED(_addr) (uint64_t)(((*((uint64_t*)(((uint32_t)_addr) & ~0x03)) >> (8*(((uint32_t)_addr) & 0x03))) & 0x000000FFFFFFFF)\
                                    | (((*((uint64_t*)(((uint32_t)_addr+4) & ~0x03))) << (32-8*(((uint32_t)_addr) & 0x03)))) & 0x00FFFF00000000)
Run Code Online (Sandbox Code Playgroud)

它基本上将整个地址移位到前一个字对齐的存储器位置,而不管偏移量.例如:

    0       1       2       3
|-------|-------|-------|-------|
|.......|.......|.......|<ADDR0>|
|<ADDR1>|<ADDR2>|<ADDR3>|<ADDR4>|
|<ADDR5>|.......|.......|.......|
Run Code Online (Sandbox Code Playgroud)

    0       1       2       3
|-------|-------|-------|-------|
|<ADDR0>|<ADDR1>|<ADDR2>|<ADDR3>|
|<ADDR4>|<ADDR5>|.......|.......|
|.......|.......|.......|.......| …
Run Code Online (Sandbox Code Playgroud)

c arm memory-alignment micro-optimization cortex-m

16
推荐指数
1
解决办法
2036
查看次数

告诉C++指针数据是16字节对齐的

我用静态数组编写了一些代码,它的矢量化很好.

float data[1024] __attribute__((aligned(16)));
Run Code Online (Sandbox Code Playgroud)

我想动态分配数组.我尝试过这样的事情:

float *data = (float*) aligned_alloc(16, size*sizeof(float));
Run Code Online (Sandbox Code Playgroud)

但是编译器(GCC 4.9.2)不再能够对代码进行矢量化.我假设这是因为它不知道指针数据是16字节对齐的.我得到的消息如下:

note: Unknown alignment for access: *_43
Run Code Online (Sandbox Code Playgroud)

我尝试在使用数据之前添加此行,但它似乎没有做任何事情:

data = (float*) __builtin_assume_aligned(data, 16);
Run Code Online (Sandbox Code Playgroud)

使用不同的变量并restrict没有帮助:

float* __restrict__ align_data = (float*) __builtin_assume_aligned(data,16);
Run Code Online (Sandbox Code Playgroud)

例:

#include <iostream>
#include <stdlib.h>
#include <math.h>

#define SIZE 1024
#define DYNAMIC 0
#define A16 __attribute__((aligned(16)))
#define DA16 (float*) aligned_alloc(16, size*sizeof(float))

class Test{
public:
    int size;
#if DYNAMIC
    float *pos;
    float *vel;
    float *alpha;
    float *k_inv;
    float *osc_sin;
    float *osc_cos;
    float *dosc1;
    float *dosc2;
#else
    float …
Run Code Online (Sandbox Code Playgroud)

c++ gcc sse memory-alignment

16
推荐指数
1
解决办法
1663
查看次数

__memcpy_sse2_unaligned - 这是什么意思?

在处理我的编译器时,我遇到了这个错误:

Program received signal SIGSEGV, Segmentation fault.
__memcpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S:33
Run Code Online (Sandbox Code Playgroud)

如何获取此处出现问题的详细信息?我从backtrace中知道它memcpy是导致它的一条线,但是我如何看待内存是如何对齐的?我怎么知道它应该如何对齐?

该项目是一个带有LLVM后端的编译器,使用Zend/PHP运行时和OCaml垃圾收集器,因此有很多问题可能出错.

我怀疑这一行是问题的一部分:

zend_string *str = (zend_string *)caml_alloc(ZEND_MM_ALIGNED_SIZE(_STR_HEADER_SIZE + len + 1), 0);
Run Code Online (Sandbox Code Playgroud)

其中caml_alloc分别pemalloc在Zend源代码.

在执行10,000个字符串连接时会发生段错误.这是valgrind的输出:

==7501== Invalid read of size 8
==7501==    at 0x4C2F790: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7501==    by 0x4D7E58: subsetphp_concat_function (bindings.c:160)
==7501==    by 0x4D7F52: foo (llvm_test.s:21)
==7501==    by 0x4D7FA9: main (llvm_test.s:60)
==7501==  Address 0x61db938 is 2,660,600 bytes inside a block of size 3,936,288 free'd
==7501==    at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) …
Run Code Online (Sandbox Code Playgroud)

c ocaml memory-alignment php-internals

16
推荐指数
1
解决办法
2万
查看次数

为什么“对齐”在32位和64位系统上相同?

我想知道编译器是否会在32位和64位系统上使用不同的填充,因此我在一个简单的VS2019 C ++控制台项目中编写了以下代码:

struct Z
{
    char s;
    __int64 i;
};

int main()
{
    std::cout << sizeof(Z) <<"\n"; 
}
Run Code Online (Sandbox Code Playgroud)

我对每个“平台”设置的期望:

x86: 12
X64: 16
Run Code Online (Sandbox Code Playgroud)

实际结果:

x86: 16
X64: 16
Run Code Online (Sandbox Code Playgroud)

由于x86上的存储字大小为4个字节,因此这意味着它必须以i两个不同的字存储字节。所以我认为编译器将以这种方式进行填充:

struct Z
{
    char s;
    char _pad[3];
    __int64 i;
};
Run Code Online (Sandbox Code Playgroud)

所以我可以知道背后的原因是什么?

  1. 是否与64位系统具有前向兼容性?
  2. 由于在32位处理器上支持64位数字的限制?

c++ abi memory-alignment 32bit-64bit visual-c++

16
推荐指数
3
解决办法
2819
查看次数

更改std :: vector的分配器时,为什么初始化程序列表不可用?

在我的项目中,我将使用过的点类型更改Eigen::Vector2fEigen::Vector2d并遇到了对齐问题.

这是代码的简化版本:

#include <vector>
#include <Eigen/Eigen>

int main()
{
    std::vector<Eigen::Vector2d> points = { {0,0}, {0,1} };
}
Run Code Online (Sandbox Code Playgroud)

我收到以下运行时错误:

eigen3/Eigen/src/Core/DenseStorage.h:78: Eigen::internal::plain_array<double, 2, 0, 16>::plain_array() [T = double, Size = 2, MatrixOrArrayOptions = 0, Alignment = 16]: Assertion `(reinterpret_cast<size_t>(array) & 0xf) == 0 && "this assertion is explained here: " "http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" " **** READ THIS WEB PAGE !!! ****"' failed.
Run Code Online (Sandbox Code Playgroud)

正如断言消息所示,我读到了固定大小的可矢量化特征对象所需的对齐.还有关于STL容器的小节.似乎我有两个选择:

  1. 使用 Eigen::aligned_allocator
  2. 或使用EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION宏.

两次尝试都不编译(使用GCC 4.8.3和Clang 3.5进行测试),因为编译器无法正确转换初始化列表.

这里改变了代码:

#include <vector> …
Run Code Online (Sandbox Code Playgroud)

c++ memory-alignment initializer-list c++11 eigen3

15
推荐指数
1
解决办法
1151
查看次数