←← →→

C99.hu

Egy gondolkodtató gyakorló feladatokból álló gyűjtemény. Főbb témák a nyelvspecifikus programozás és a matematika.

Főoldal

Az L1 gyorsítótár nyoma

C++
Nehézség: Gondolkodtató

Egy rendszerprogramozó azt vizsgálja, mennyi idő kell az L1 cache újratöltéséhez. A feladat az, hogy elemezze a kódot, értse meg, mit mér, és becsülje meg, milyen hardverjelenséget használ ki.

#include <iostream>
#include <vector>
#include <cstdint>
#include <chrono>
#include <new>

using namespace std::chrono;

auto L1RefillLatency(){
constexpr size_t CacheLineSize = std::hardware_destructive_interference_size;
constexpr auto TotalBufferSize = CacheLineSize * (2 << 12);
constexpr auto Trials = 20'000;

std::vector<uint8_t> CacheLineData(CacheLineSize), CacheLineEvictData(TotalBufferSize);
volatile uint64_t sink = 0;

auto floodTime = 0.0;

const auto startTrialing = steady_clock::now();

for(size_t trials = 0; trials < Trials; trials++){
auto floodStart = steady_clock::now();

for(size_t i = 0; i< CacheLineEvictData.size(); i+=CacheLineSize){
sink += CacheLineEvictData[i];
}

auto floodEnd = steady_clock::now();

const auto iterationFloodTime = duration_cast<nanoseconds>(floodEnd-floodStart).count();

floodTime += static_cast<double>(iterationFloodTime);

sink += CacheLineData[0];
}

const auto endTrialing = steady_clock::now();
const auto totalTrialTime = static_cast<double>(duration_cast<nanoseconds>(endTrialing-startTrialing).count());

const auto totalReadLatency = totalTrialTime - floodTime;
return totalReadLatency / Trials;
}

int main() {
std::cout << L1RefillLatency() << " ns" << std::endl;

return 0;
}

-- Feladatok:
-- 1. Magyarázza el, milyen hardverjelenséget próbál mérni a program.
-- 2. Miért lép a kód CacheLineSize-os lépésközzel a memórián?
-- 3. Miért használ a program egy külön evict tömböt a mérés előtt?
-- 4. Milyen szerepe van a volatile sink változónak?


MegoldásMegoldási ötletek:
1. A program az L1 cache-ből kilökött adat újratöltési késleltetését próbálja becsülni.
2. A cache line-os lépésköz a cache-sorok érintésére és az előbetöltés/caching hatások csökkentésére szolgál.
3. Az evict tömb kiűzi az adatot a gyorsítótárból, hogy a következő hozzáférés cache miss legyen.
4. A volatile sink megakadályozza, hogy a fordító optimalizálja el a memóriaműveleteket.