标签: memory-alignment

查询特定变量的对齐方式

C++ 11引入了alignas说明符来指定变量的对齐方式,以及alignof运算符来查询类型的默认对齐方式.但是,我没有看到任何方法来获得特定变量的对齐方式.让我们采取以下简单的例子:

alignas(16) float* array;
Run Code Online (Sandbox Code Playgroud)

以下是我们可以做的事情:

  • alignof(float*) 返回8,这显然不是我们想要的.
  • alignof(array)返回16,这正是我们想要的,但这是一个编译器扩展; alignof由标准指定不能用于特定变量.
  • alignof(decltype(array)) 返回8,这是非常期待但不是我们想要的.
  • std::alignment_of是实施的alignof,所以它没有多大帮助.

我想要一种机制来确认特定变量array是否在16字节边界上对齐.标准中是否有任何内容可以执行此类查询?

c++ memory-alignment c++11

34
推荐指数
2
解决办法
1365
查看次数

C++中的原子性:神话还是现实

我一直在阅读一篇关于MSDN中的无锁编程的文章.它说 :

在所有现代处理器上,您可以假设自然对齐的本机类型的读取和写入 是原子的.只要存储器总线至少与读取或写入的类型一样宽,CPU就会在单个总线事务中读取和写入这些类型,这使得其他线程无法在半完成状态下看到它们.

它给出了一些例子:

// This write is not atomic because it is not natively aligned.
DWORD* pData = (DWORD*)(pChar + 1);
*pData = 0;

// This is not atomic because it is three separate operations.
++g_globalCounter;

// This write is atomic.
g_alignedGlobal = 0;

// This read is atomic.
DWORD local = g_alignedGlobal;
Run Code Online (Sandbox Code Playgroud)

我读了很多答案和评论说,没有什么能保证在C++中是原子的,甚至在标准中都没有提到,在SO中,现在我有点困惑.我误解了这篇文章吗?或者文章作者是否谈论了非标准和特定于MSVC++编译器的内容?

所以根据这篇文章,下面的作业必须是原子的,对吧?

struct Data
{
    char ID;
    char pad1[3];
    short Number;
    char pad2[2];
    char Name[5];
    char pad3[3];
    int Number2;
    double …
Run Code Online (Sandbox Code Playgroud)

c++ atomic memory-alignment

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

关于Hinnant的堆栈分配器的问题

我一直在使用Howard Hinnant的堆栈分配器,它就像一个魅力,但实现的一些细节对我来说有点不清楚.

  1. 为什么全球运营商newdelete使用?的allocate()deallocate()成员函数使用::operator new::operator delete分别.同样,成员函数construct()使用全局布局new.为什么不允许任何用户定义的全局或类特定的重载?
  2. 为什么对齐设置为硬编码16字节而不是std::alignment_of<T>
  3. 为什么构造函数和max_sizethrow()异常规范?这不是劝阻(参见例如更有效的C++第14项)?在分配器中发生异常时,是否真的有必要终止和中止?这是否随新的C++ 11 noexcept关键字而改变?
  4. construct()成员函数将是完美转发(在构造函数被调用)的理想选择.这是编写符合C++ 11标准的分配器的方法吗?
  5. 还需要进行哪些其他更改才能使当前代码C++ 11符合要求?

c++ memory-alignment exception-specification allocator c++11

32
推荐指数
1
解决办法
3149
查看次数

如何检查指针是否指向正确对齐的内存位置?

给定void *一些存储,如何检查它是否指向正确对齐的存储而没有任何实现定义的行为?

我们当然有std::align,但是有更有效的方法吗?

template <std::size_t alignment>
inline bool is_aligned(void * ptr) noexcept {
    std::size_t max = 1u;
    return std::align(alignment, 1u, ptr, max);
}
Run Code Online (Sandbox Code Playgroud)

PS:我需要以兼容C++标准的方式执行此操作,而不依赖于任何特定于平台的(实现定义的)黑客攻击.

PPS:我为我(理解)英语而道歉,而不是我的母语.


EDIT(2018.08.24):从标题中删除了"有效",添加了更多的措辞,强调我不希望任何实现定义或特定于平台的行为.

c++ memory-alignment c++11 c++14 c++17

30
推荐指数
1
解决办法
3397
查看次数

当int64_t更改为int32_t时,为什么类大小会增加

在我的第一个例子中,我使用了两个位域int64_t.当我编译并获得类的大小时,我得到8.

class Test
{
    int64_t first : 40;
    int64_t second : 24;
};

int main()
{
    std::cout << sizeof(Test); // 8
}
Run Code Online (Sandbox Code Playgroud)

但是,当我将第二个bitfeild更改int32_t为类的大小时,会增加到16:

class Test
{
    int64_t first : 40;
    int32_t second : 24;
};

int main()
{
    std::cout << sizeof(Test); // 16
}
Run Code Online (Sandbox Code Playgroud)

这种情况发生在GCC 5.3.0和MSVC 2015上.但为什么呢?

c++ memory-alignment memory-layout bit-fields object-layout

28
推荐指数
4
解决办法
2174
查看次数

获得对齐内存的最佳跨平台方法

这是我通常用于通过Visual Studio和GCC获得对齐内存的代码

inline void* aligned_malloc(size_t size, size_t align) {
    void *result;
    #ifdef _MSC_VER 
    result = _aligned_malloc(size, align);
    #else 
     if(posix_memalign(&result, align, size)) result = 0;
    #endif
    return result;
}

inline void aligned_free(void *ptr) {
    #ifdef _MSC_VER 
        _aligned_free(ptr);
    #else 
      free(ptr);
    #endif

}
Run Code Online (Sandbox Code Playgroud)

这个代码一般是好的吗?我也见过人们用_mm_malloc,_mm_free.在大多数情况下,我想要对齐内存,使用SSE/AVX.我可以一般使用这些功能吗?它会使我的代码更简单.

最后,创建我自己的函数来对齐内存很容易(见下文).为什么会有这么多不同的常用函数来获得对齐的内存(其中许多只能在一个平台上运行)?

此代码执行16字节对齐.

float* array = (float*)malloc(SIZE*sizeof(float)+15);

// find the aligned position
// and use this pointer to read or write data into array
float* alignedArray = (float*)(((unsigned long)array + 15) & (~0x0F));

// dellocate memory …
Run Code Online (Sandbox Code Playgroud)

c c++ performance sse memory-alignment

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

幻像类型与原始类型具有相同的对齐方式吗?

请考虑以下包含一些环境值的结构:

struct environment_values {
  uint16_t humidity;
  uint16_t temperature;
  uint16_t charging;
};
Run Code Online (Sandbox Code Playgroud)

我想为这些带有幻像类型*的值添加一些额外的信息,并同时使它们的类型不同:

template <typename T, typename P>
struct Tagged {
    T value;
};

// Actual implementation will contain some more features
struct Celsius{};
struct Power{};
struct Percent{};

struct Environment {
  Tagged<uint16_t,Percent> humidity;
  Tagged<uint16_t,Celsius> temperature;
  Tagged<uint16_t,Power>   charging;
};
Run Code Online (Sandbox Code Playgroud)

内存布局是Environment一样的environment_values吗?这是否也适用于混合类型布局,例如:

struct foo {
    uint16_t value1;
    uint8_t  value2;
    uint64_t value3;
}

struct Foo {
    Tagged<uint16_t, Foo>  Value1;
    Tagged<uint8_t , Bar>  Value2;
    Tagged<uint64_t, Quux> Value3;
}
Run Code Online (Sandbox Code Playgroud)

对于我迄今为止尝试过的所有类型,以下断言都是:

template <typename T, …
Run Code Online (Sandbox Code Playgroud)

c++ struct types memory-alignment language-lawyer

26
推荐指数
2
解决办法
535
查看次数

GCC无法像C阵列一样优化对齐的std :: array

以下是GCC 6和7在使用时无法优化的一些代码std::array:

#include <array>

static constexpr size_t my_elements = 8;

class Foo
{
public:
#ifdef C_ARRAY
    typedef double Vec[my_elements] alignas(32);
#else
    typedef std::array<double, my_elements> Vec alignas(32);
#endif
    void fun1(const Vec&);
    Vec v1{{}};
};

void Foo::fun1(const Vec& __restrict__ v2)
{
    for (unsigned i = 0; i < my_elements; ++i)
    {
        v1[i] += v2[i];
    }
}
Run Code Online (Sandbox Code Playgroud)

编译上面的g++ -std=c++14 -O3 -march=haswell -S -DC_ARRAY代码会产生很好的代码:

    vmovapd ymm0, YMMWORD PTR [rdi]
    vaddpd  ymm0, ymm0, YMMWORD PTR [rsi]
    vmovapd YMMWORD PTR [rdi], ymm0 …
Run Code Online (Sandbox Code Playgroud)

c++ optimization gcc simd memory-alignment

24
推荐指数
1
解决办法
3914
查看次数

使用贴片新操作符时,我真的不得不担心对齐吗?

我读过这个 什么时候应该担心对齐?但我仍然不知道我是否要担心放置新运算符返回的对齐指针 - 就像在这个例子中:

class A {
public:
   long double a;
   long long b;
   A() : a(1.3), b(1234) {}
};

char buffer[64];

int main() {
   // (buffer + 1) used intentionally to have wrong alignment
   A* a = new (buffer + 1) A(); 
   a->~A();
}
Run Code Online (Sandbox Code Playgroud)

__alignof(A) == 4,(buffer + 1)是不对齐的4.但一切正常 - 这里有完整的例子:http://ideone.com/jBrk8

如果这取决于架构,那么我正在使用:linux/powerpc/g ++ 4.xx

[更新]发布此问题后,我读了这篇文章:http://virtrev.blogspot.de/2010/09/memory-alignment-theory-and-c-examples.html.也许在我的情况下唯一的缺点是性能损失,我的意思是未对齐的访问成本超过对齐?

c++ g++ powerpc memory-alignment placement-new

23
推荐指数
2
解决办法
5129
查看次数

标准对未对齐的内存访问有何看法?

我搜索了关于未对齐访问的标准,但没有找到任何东西(也许我是无意的).

是不确定的行为?它是实现定义的吗?

由于许多当前的CPU支持未对齐访问,因此未对齐的内存访问是实现定义的,这是明智的.是这样的吗?

通过未对齐访问,我的意思是例如:

alignas(int) char buffer[sizeof(int)+1];
int &x = *new(buffer+1) int;
x = 42;
Run Code Online (Sandbox Code Playgroud)

c++ memory-alignment language-lawyer c++17

23
推荐指数
1
解决办法
1334
查看次数