Следующий пример кода генерирует матрицу размера N и переносит ее SAMPLES количество раз.
Когда N = 512 среднее время выполнения операции транспонирования 2144 μs (ссылка coliru).
На первый взгляд нет ничего особенного, правильно?...
Ну, вот результаты для
-  
N = 513→1451 μs -  
N = 519→600 μs -  
N = 530→486 μs -  
N = 540→492 μs(наконец, теория начинает работать:). 
Итак, почему на практике эти простые вычисления так отличаются от теории? Связано ли это с когерентностью кэш-памяти процессора или пропуском кэша? Если да, пожалуйста, объясните.
#include <algorithm>
#include <iostream>
#include <chrono>
constexpr int N       = 512; // Why is 512 specifically slower (as of 2016)
constexpr int SAMPLES = 1000;
using us = std::chrono::microseconds;
int A[N][N];
void transpose()
{
    for ( int i = 0 ; i < N ; i++ )
    for ( int j = 0 ; j < i ; j++ )
        std::swap(A[i][j], A[j][i]);
}
int main()
{
    // initialize matrix
    for ( int i = 0 ; i < N ; i++ )
    for ( int j = 0 ; j < N ; j++ )
        A[i][j] = i+j;
    auto t1 = std::chrono::system_clock::now();
    for ( int i = 0 ; i < SAMPLES ; i++ )
        transpose();
    auto t2 = std::chrono::system_clock::now();
    std::cout << "Average for size " << N << ": " << std::chrono::duration_cast<us>(t2 - t1).count() / SAMPLES << " (us)"; 
}