Attribute to enforce padding after a variable?
Asked Answered
H

3

10

Is there an attribute to enforce padding after a variable?

I have a volatile (non-cached) variable declared as such:

volatile int foo __attribute__((aligned(CACHE_LINE_SIZE));

I would like to prevent other variables from being allocated to the same cache line, to avoid coherency issues. I can add a padding variable after foo, or set the __attribute__((aligned(CACHE_LINE_SIZE)) to the following variable in the same compilation unit. However I was wondering whether there is a cleaner way to do this, such as adding an attribute to variable foo itself to enforce padding.

Hemicellulose answered 22/5, 2023 at 8:26 Comment(5)
something along struct { int foo; char padding[CACHE_LINE_SIZE - sizeof(int)]; }?Berkley
Does std::aligned_storage do what you want ?Rese
@Berkley With your definition, there is no guarantee that an object will be mapped to a single cache line only.Guerrero
The union { int foo; char size[CACHE_LINE_SIZE]; } looks even better.Berkley
@RichardCritten Even if it did, std::aligned_storage has been deprecated in C++23.Sorehead
S
4

Some options are introduced in this blog article: Aligning data with cache lines.

I would suggest to use the C++11 alignas:

The simplest version

using my_padded_type = struct alignas(CACHE_LINE_SIZE) { int value;} ;

Padding bits are added automatically. You can verify it by checking sizeof(my_padded_type). See details below.

Other options:

alignas(CACHE_LINE_SIZE) int foo1, foo2;
alignas(CACHE_LINE_SIZE) union { int value; char size[CACHE_LINE_SIZE]; } foo;

std::cout  << "&foo1: " << &foo1 << '\t'
           << "&foo2: " << &foo2 << '\n';
// &foo1: 0x7ffd833ebe00 &foo2: 0x7ffd833ebe40

or

struct alignas(CACHE_LINE_SIZE) my_padded_type {
    int foo;  //  size: 4 
    char p;   //  do not need to specify length here. this line can be omitted entirely
    // auto padding so that sizeof(my_padded_type) == CACHE_LINE_SIZE
}; 
my_padding_type foo;
std::cout<< sizeof(my_padding_type) <<"\n"; // equals CACHE_LINE_SIZE

The padding is done automatically by the compiler, see the example here.

Striation answered 22/5, 2023 at 9:38 Comment(0)
S
4

This is what std::hardware_destructive_interference_size was added for:

struct X
{
    alignas(std::hardware_destructive_interference_size) int Foo;
    alignas(std::hardware_destructive_interference_size) int Bar; // Foo and Bar are on different cache lines
};
alignas(std::hardware_destructive_interference_size)
struct Foo // Foo is guaranteed to be on its own cache line
{
};
Sorehead answered 22/5, 2023 at 17:13 Comment(1)
Can you find a reference / standard documentation about the behavior of alignas(64) struct Foo {}? I have tested in GCC/Clang. Both compiler do guarantee Foo to be on its own cache line. However I cannot find any guarantee in the C++ standard.Striation
I
3

alignas(CACHE_LINE_SIZE) on every variable should to the trick:

struct X {
    alignas(CACHE_LINE_SIZE) int foo;
    alignas(CACHE_LINE_SIZE) int bar;
};

Live demo

I assume you are asking about aligning struct members.

If you don't care about the alignment of subsequent members, but want to make sure that no other data is placed on foo's cache line, manually fill it with padding bytes:

struct X {
    alignas(CACHE_LINE_SIZE) int foo;
    char paddingbytes[CACHE_LINE_SIZE - sizeof(int)];
    // Other data members
};
Indusium answered 22/5, 2023 at 10:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.