CodeNebula
C++20stladvanced

std::assume_aligned (C++20 Addition)

C++20 · The Big Four · Compiler flag: -std=c++20

Explanation

Informs the compiler that a pointer is aligned to at least N bytes, enabling SIMD and other alignment-dependent optimizations. Returns the same pointer with the alignment guarantee baked in.

Real-World Scenario

Optimize a SIMD-accelerated image processing kernel by asserting 32-byte alignment on pixel data.

Quick Snippet

snippet.cpp
#include <memory>

void process_pixels(float* data, std::size_t n) {
    float* aligned = std::assume_aligned<32>(data);
    for (std::size_t i = 0; i < n; ++i)
        aligned[i] *= 2.0f;  // compiler can emit AVX instructions
}

Full Example

assume_aligned.cpp
// CodeNebula - C++20 Example: std::assume_aligned
// Compile: g++ -std=c++20 -Wall -Wextra -o example assume_aligned.cpp

#include <cstdlib>
#include <iostream>
#include <memory>
#include <numeric>

// std::assume_aligned<N>(ptr) returns ptr with a compiler hint
// that it is aligned to N bytes, enabling SIMD optimizations

// Process array with alignment hint for vectorization
void process_aligned(float* data, std::size_t n) {
    // Tell the compiler this pointer is 64-byte aligned
    float* aligned_data = std::assume_aligned<64>(data);
    for (std::size_t i = 0; i < n; ++i) {
        aligned_data[i] *= 2.0f;
    }
}

// Sum with alignment hint
float sum_aligned(const float* data, std::size_t n) {
    const float* aligned_data = std::assume_aligned<32>(data);
    float total = 0.0f;
    for (std::size_t i = 0; i < n; ++i) {
        total += aligned_data[i];
    }
    return total;
}

int main() {
    constexpr std::size_t N = 16;
    constexpr std::size_t alignment = 64;

    std::cout << "=== std::assume_aligned optimization hint ===\n";

    // Allocate aligned memory
    float* data = static_cast<float*>(
        std::aligned_alloc(alignment, N * sizeof(float)));

    if (!data) {
        std::cerr << "Allocation failed\n";
        return 1;
    }

    // Verify alignment
    auto addr = reinterpret_cast<std::uintptr_t>(data);
    std::cout << "Pointer address: " << data << "\n";
    std::cout << "Aligned to " << alignment << " bytes: "
              << (addr % alignment == 0 ? "yes" : "no") << "\n";

    // Initialize
    std::iota(data, data + N, 1.0f);  // 1, 2, 3, ..., 16

    std::cout << "\nBefore processing: ";
    for (std::size_t i = 0; i < N; ++i) std::cout << data[i] << " ";
    std::cout << "\n";

    // Process with alignment hint
    process_aligned(data, N);

    std::cout << "After processing:  ";
    for (std::size_t i = 0; i < N; ++i) std::cout << data[i] << " ";
    std::cout << "\n";

    float total = sum_aligned(data, N);
    std::cout << "Sum of processed:  " << total << "\n";
    std::cout << "Expected:          " << N * (N + 1) << "\n";

    std::free(data);

    std::cout << "\n=== Note ===\n";
    std::cout << "assume_aligned is a compiler hint only.\n";
    std::cout << "Using it on unaligned memory is undefined behavior.\n";

    return 0;
}
Run command
g++ -std=c++20 -Wall -Wextra -o example assume_aligned.cpp