8 Ocak 2018 Pazartesi

alignas

Giriş
Bu yapı ile iki tane aynı nesneyi yanyana koyarsak ne kadar hizalama belleği kullanılacağını belirtiriz.

array
Şöyle yaparız.
typedef unsigned char Type;

const int N = 4;

alignas(64) Type buffer[N*64];
struct
Örnek
Şöyle yaparız.
struct alignas(16) small16 {
  char c;
};
Örnek
Elimizde şöyle bir kod olsun. Derleyici optimizedEqual() ve optimizedEqual2() kodları için hızlı kod üretiyor. Yani std::memcpy() ve std::memcmp() hızı çalışıyor. Ancak alanları tek tek karşılaştırma kodları hızlı değil.
struct Point {
  std::int32_t x, y;
};

[[nodiscard]]
bool naiveEqual(const Point &a, const Point &b) {
  return a.x == b.x && a.y == b.y;
}

[[nodiscard]]
bool optimizedEqual(const Point &a, const Point &b) {
  // Why can't the compiler produce the same assembly in naiveEqual as it does here?
  std::uint64_t ai, bi;
  static_assert(sizeof(Point) == sizeof(ai));
  std::memcpy(&ai, &a, sizeof(Point));
  std::memcpy(&bi, &b, sizeof(Point));
  return ai == bi;
}

[[nodiscard]]
bool optimizedEqual2(const Point &a, const Point &b) {
  return std::memcmp(&a, &b, sizeof(a)) == 0;
}


[[nodiscard]]
bool naiveEqual1(const Point &a, const Point &b) {
  // Let's try avoiding any jumps by using bitwise and:
  return (a.x == b.x) & (a.y == b.y);
}
Düzeltmek için şöyle yaparız. Point sınıfı 64 bit olacak şekilde hizalanırsa yani varsa aradaki "data alignment" byte'ları kaldırılırsa, derleyici 64 bşt karşılaştırma yapabilir.
struct alignas(std::int64_t) Point {
    std::int32_t x, y;
};
Primitive
Şöyle yaparız.
alignas(64) double bar;
Gcc Extension
Şöyle yaparız
typedef uint32_t __attribute__ ((aligned (64))) aligned_uint32_t;
std::cout << sizeof(aligned_uint32_t) << " -> " << alignof(aligned_uint32_t);
// Output: 4 -> 64
placement new
Örnek
Önce align edilmiş bir bellek alanı hazırlarız.
alignas(Foo) char memory[sizeof(Foo)];
Neden bilmiyorum ancak şu kullanım yanlış.
char memory[sizeof(Foo)];
Sonra placement new kullanarak şöyle yaparız.
::new (static_cast<void*>(buf)) Foo;
Örnek
Şöyle yaparız. Burada bellek alanı olarak daha büyük bir yer veriliyor.
alignas(int) unsigned char buffer[2*sizeof(int)];
 auto p1=new(buffer) int{};

Hiç yorum yok:

Yorum Gönder