Open
Close

За що відповідає кеш у процесорі. Новий підхід до кешування процесора. Який буває обсяг і на що він впливає

Кеш процесора- Спеціальна пам'ять усередині процесора для прискорення звернення до оперативної пам'яті. Іноді кеш процесора називають надоперативною пам'яттю, тому що доступ до неї відбувається за дуже короткий час. Зазвичай кеш у процесорах роблять на основі класичних тригерів – так званої статичної пам'яті (SRAM). Наприклад, оперативна пам'ять побудована з урахуванням конденсаторів, які іноді заряджаються. Тригери забезпечують практично миттєвий доступ до себе, але вони мають дві головні недоліки:

  • відносно висока вартість виготовлення
  • постійне споживання енергії
  • Саме ці обмеження SRAM не дозволяють робити на основі її оперативну пам'ять.

    Рівні кешу процесора

    У сучасних процесорах кеш поділяється на кілька рівнів

    Алгоритм роботи кеш пам'яті

    Алгоритмом роботи кеша управляє спеціальний контролер, розташований у процесорі. Він може динамічно змінювати свою схему роботи залежно від обставин. Але загальний алгоритм кешу такий:

    Коли процесор робить запит на читання, контролер кешушукає значення у кеші і якщо воно знайдено, відправляє його процесору. Якщо значення не знайдено, то контролер відправляє запит далі: або кешу нижчого рівня, або оперативну пам'ять. Після читання значення з нижчого рівня, кеш додає це значення собі і за наступному зверненні - відразу віддасть його процесору.

    Коли процесор робить запит на запис на оперативну пам'ять, то контролер кешуоновлює значення в себе і передає його далі – на нижчі рівні. Зрештою значення виявляється в оперативній пам'яті. За таким алгоритмом працює кеш на запис. Можна, звичайно, зберігати значення тільки до кешу, але тоді інші компоненти (наприклад, DMA - прямий доступ до пам'яті) при доступі до оперативної пам'яті ризикують отримати застаріле значення.

    Частота роботи кеш-пам'яті

    Оскільки SRAM пам'ять можуть працювати на дуже великих частотах, кеш-пам'ять процесора зазвичай працює на тій же частоті, що і сам процесор. Це додатково збільшує швидкість роботи із цим видом пам'яті.

    Інтелектуальна кеш-пам'ять

    Сучасні кеш-контролери вміють вгадувати, до яких осередків пам'яті процесор швидко звернутися і заздалегідь завантажує з кеш. Наприклад, якщо процесор звернувся до комірки 42, потім до 43, то висока ймовірність того, що третє звернення буде до комірки 44. Тому контролер заздалегідь завантажує значення комірки 44 собі надшвидку пам'ять.

    Перший кеш

    Деяка подоба кешу була ще в процесорі 8086. У ньому було 6 байт кешу команд. Невелика кількість без великих інтелектуальних здібностей, але він значно підвищував швидкодію системи. Але справжній кеш став використовуватися з процесором 80386. У ті часи для звернення до оперативної пам'яті потрібно 120 нс часу. Але поряд із процесоромставили спеціальну мікросхему кеш-пам'ятіі доступ до неї відбувався у 12 разів швидше, ніж до оперативної пам'яті. Але ця пам'ять (SRAM) була досить дорогою та ставити мікросхему кеш пам'яті великого обсягу було нерентабельно. Тому перші кеші процесора були обмежені об'ємом 64 кілобайт і встановлювалися окремо. Починаючи з процесора 80486 кеш процесорастав виправдовувати свою назву, тому що встановлювався прямо у процесорі.

    Місце встановлення кешу

    Як було зазначено вище, в процесорі 80386 був внутрішнього кеша. Кеш встановлювався окремою мікросхемою на материнській платі. У комп'ютерах на базі процесора 80486 як раніше на материнській платі розміщувався кеш, але це був другий рівень. Перший рівень кешу встановлювався прямо в процесорі. З часом та розвитком технології виготовлення мікросхем кеш процесора повністю переїхав у процесор, як і контролер оперативної пам'яті.

    Кеш процесорає ефективним способом збільшити продуктивність процесора, за рахунок збільшення швидкості роботи з оперативною пам'яттю.

    Першим процесором, який вироблявся з кешем L2, став Pentium Pro у 1995 році. Він мав 256 або 512 кбайт кешу другого рівня на кристалі, що давало істотну перевагу над звичайними процесорами Pentium, чий кеш розташовувався на материнській платі. З появою Pentium II у модулі Slot 1 виділена кеш-пам'ять "оселилася" поруч із процесором. Але лише у другого покоління Pentium III для Socket 370 кеш-пам'ять перейшла на кристал процесора. Так триває і донині, але є процесори з невеликою кількістю кешу, а є з більшим. Чи варто витрачати гроші на модель із великим кешем? У минулому додаткова кеш-пам'ять не завжди відчутно впливала на продуктивність.

    Хоча завжди можна знайти різниці між двома процесорами з різними розмірами кешу, для економії коштів цілком можна було купувати процесори з меншим кешем. Але жоден процесор до появи Core 2 Duo був доступний з трьома різними варіантами кеша.

    Pentium 4 у своєму першому поколінні (Willamette, 180 нм) оснащувався 256 кбайт кешу, а успішнішому другому поколінні (Northwood, 130 нм) - вже 512 кбайт кешу. Тоді дешеві процесори Celeron з меншим кешем вироблялися тих самих обчислювальних ядрах. Celeron відносяться до першого покоління продуктів з однією технологічною базою для high-end та дешевих моделей, що відрізняються лише доступним розміром кешу та частотами FSB/ядра. Пізніше було додано і різниця у функціях, щоб помітніше розділити сегменти ринку.

    З випуском 90-нм ядра Prescott обсяг кешу L2 виріс до 1 Мбайт, і цей процесор став основою лінійки настільних процесорів Intel до появи 2-Мбайт 65-нм Cedar Mill. Intel навіть використовувала два таких ядра для створення процесорів Pentium D 900 другого покоління. Втім, більш швидкі тактові частоти та більший обсяг кешу навіть тоді не означали дуже багато. Сьогодні ситуація змінилася: краща продуктивність Core 2 Duo (Conroe, 65 нм) та менше енергоспоживання чимало завдячують розміру кешу.

    AMD дуже стримано ставилася до збільшення обсягу кешу. Швидше за все це пов'язано з площею кристала (бюджетом транзисторів), оскільки кількість 65-нм процесорів не може задовольнити попит на ринку, а у менш вигідних 90-нм моделей це питання стоїть ще гостріше. У Intel, з іншого боку, є перевага у вигляді виробництва всіх масових процесорів по 65-нм техпроцесу, та й ємність кешу L2 ще зростатиме. Наприклад, наступне покоління Core 2 на 45-нм ядрі Penryn оснащуватиметься до 6 Мбайт кешу L2. Чи можна розглядати це як маркетинговий крок, чи збільшення ємності L2 справді дасть приріст продуктивності? Давайте подивимося.

    Великий кеш L2: маркетинг чи зростання продуктивності?

    Кеші процесора грають цілком певну роль: вони зменшують кількість звернень до пам'яті, буферизуючи дані, що часто використовуються. Сьогодні ємність ОЗУ становить від 512 Мбайт до 4 Гбайт, а об'єм кешу – від 256 кбайт до 8 Мбайт, залежно від моделі. Втім, навіть невеликого обсягу кешу в 256 або 512 кбайт достатньо, щоб забезпечити високу продуктивність, яку сьогодні сприймають само собою зрозумілою.

    Існують різні способи організації ієрархії кешу. У більшості сучасних комп'ютерів встановлені процесори з невеликим кешем першого рівня (L1, до 128 Кбайт), який зазвичай поділяється на кеш даних та кеш інструкцій. Кеш L2 більшого розміру зазвичай використовується для зберігання даних, він є загальним для двох процесорних ядер Core 2 Duo, хоча Athlon 64 X2 або Pentium D мають окремі кеші на ядро. Кеш L2 може працювати ексклюзивно або інклюзивно, тобто він може або зберігати копію вмісту L1 кешу, або ні. AMD незабаром представить процесори з третім рівнем кешу, який буде загальним для чотирьох ядер у процесорах AMD Phenom. Те саме очікується і для архітектури Nehalem, яку Intel представить у 2008 році на заміну поточним Core 2.

    Кеш L1 завжди був у складі процесора, але спочатку кеш L2 встановлювався на материнські плати, як було у випадку багатьох комп'ютерів 486DX та Pentium. Для кеш-пам'яті першого рівня використовувалися прості чіпи статичної пам'яті (SRAM, Static RAM). Вони незабаром були замінені на конвеєрний пакетний кеш (pipelined burst cache) у процесорів Pentium, поки не з'явилася можливість встановлювати кеш на кристал. Pentium Pro на 150 – 200 МГц став першим процесором, що містить 256 кбайт кеш-пам'яті L2 на кристалі, побивши рекорд за розміром керамічної упаковки для настільних ПК та робочих станцій. Pentium III для Socket 370, що працює на частотах від 500 МГц до 1,13 ГГц, став першим процесором з 256 кбайт кеш-пам'яті на кристалі L2, що давало перевагу зниження затримок, оскільки кеш працює на частоті CPU.

    Вбудований кеш L2 дав суттєвий приріст продуктивності практично у будь-яких додатках. Збільшення продуктивності виявилося настільки суттєвим, що поява інтегрованого кеша L2 можна назвати найважливішим фактором продуктивності процесорів x86. Відключення кешу L2 зменшить продуктивність сильніше, ніж відключення другого ядра у двоядерного процесора.

    Однак кеш-пам'ять впливає не лише на продуктивність. Вона стала потужним інструментом, що дозволяє створювати різні моделі процесорів для low-end, масового та high-end сегментів, оскільки виробник може гнучко відбирати процесори з відбраковування та тактових частот. Якщо кристалі немає дефектів, можна включити весь кеш L2, та й частоти виходять високі. Якщо ж бажаних тактових частот досягти не вдасться, кристал може стати моделлю початкового рівня в high-end лінійці, наприклад, Core 2 Duo 6000 з 4 Мбайт кешу і низькими частотами. Якщо дефекти присутні в кеші L2, то виробник має можливість відключити його частину і створити модель початкового рівня з меншим об'ємом кешу, наприклад, Core 2 Duo E4000 з 2 Мбайт кешу L2 або навіть Pentium Dual Core лише з 1 Мбайт кешу. Все це справді так, але питання полягає в наступному: наскільки різниця в обсязі кешу впливає на продуктивність?

    Варіанти Core 2 Duo

    Intel випустила ринок великий асортимент настільних процесорів. Сьогодні ще можна знайти Pentium 4 та Pentium D, але більшість моделей побудовано на мікро-архітектурі Core. Ми не рекомендуємо брати процесори Pentium 4 або Pentium D, хоча їх частоти тактові до 3,8 ГГц можуть виглядати привабливо. Але будь-який процесор Core 2 на частоті 2,2 ГГц і вище може перемогти навіть найшвидші моделі Pentium D (власне, як і Athlon 64 X2), оскільки Core 2 дає набагато кращу продуктивність на такт .

    Завдяки меншим тактовим частотам процесори Core 2 ефективніші з енергоспоживання. Якщо топові моделі Pentium D 800 "з'їдають" до 130 Вт, лише Core 2 Extreme з чотирма ядрами долає поріг 100 Вт. Усі двоядерні процесори споживають не більше 65 Вт. Крім того, енергоспоживання в режимі бездіяльності процесорів Core 2 Duo ще нижче, оскільки робоча частота в режимі бездіяльності менша (максимум 1,2 ГГц для Core 2 Duo/Quad проти 2,8 ГГц Pentium D/4). На зниження енергоспоживання вплинув покращений дизайн транзисторів із зменшеними струмами витоку.

    Сьогодні доступні моделі E та X. Моделі E призначені для масового ринку, а X відносяться до класу Extreme Edition. Q позначає чотири ядра, які Intel створює, розміщуючи два двоядерні кристали в одній фізичній упаковці. Процесори E6000 оснащені 4 Мбайт кешу L2, якщо їх модельний номер вищий за E6400 або закінчується на 20 (наприклад, E6320). Моделі, що закінчуються на 00 (наприклад, E6600), працюють з FSB 266 МГц (FSB1066), а моделі, що закінчуються на 50 (E6750), працюють з FSB 333 МГц (FSB1333). Остання вимагає чіпсету P35 або X38 і дає трохи більшу продуктивність. E4000 працює з FSB 200 МГц (FSB800) і має лише 2 Мбайт кешу L2. Версії з 1 Мбайт кешу продаються як Pentium Dual Core E2140, E2160 та E2180 з частотами від 1,6 до 2,0 ГГц. Крім назви та деяких функцій, які Intel відключає у дешевих процесорів, згадані моделі Pentium Dual Cores ідентичні Core 2 Duo.

    Характеристики процесорів Core 2 Duo
    Номер 65-нм процесора Кеш Тактова частота FSB Технологія віртуалізації Технологія Trusted Execution
    E6850 4 Мбайт L2 3 ГГц 333 МГц X X
    E6750 4 Мбайт L2 2,66 ГГц 333 МГц X X
    E6700 4 Мбайт L2 2,66 ГГц 266 МГц X
    E6600 4 Мбайт L2 2,40 ГГц 266 МГц X
    E6550 4 Мбайт L2 2,33 ГГц 333 МГц X X
    E6540 4 Мбайт L2 2,33 ГГц 333 МГц X
    E6420 4 Мбайт L2 2,13 ГГц 266 МГц X
    E6400 2 Мбайт L2 2,13 ГГц 266 МГц X
    E6320 4 Мбайт L2 1,86 ГГц 266 МГц X
    E6300 2 Мбайт L2 1,86 ГГц 266 МГц X
    E4600 2 Мбайт L2 2,40 ГГц 200 МГц
    E4500 2 Мбайт L2 2,20 ГГц 200 МГц
    E4400 2 Мбайт L2 2 ГГц 200 МГц
    E4300 2 Мбайт L2 1,80 ГГц 200 МГц


    Платформа
    CPU I Intel Pentium Dual Core E2160 (65 нм; 1800 МГц, 1 Мбайт кешу L2) на частоті 2,4 ГГц (266 МГц x9)
    CPU II Intel Core 2 Duo E4400 (65 нм; 2000 МГц, 2 Мбайт кешу L2) на частоті 2,4 ГГц (266 МГц x9)
    CPU III Intel Core 2 Duo X6800 (65 нм; 3000 МГц, 4 Мбайт кешу L2) на частоті 2,4 ГГц (266 МГц x9)
    Материнська плата ASUS Blitz Formula, Rev: 1.0
    Чіпсет: Intel P35, BIOS 1101
    Пам'ять Corsair CM2X1024-888C4D, 2x 1024 Мбайт DDR2-800 (CL 4-4-4-12 2T)
    Жорсткий диск Western Digital Raptor WD1500ADFD, 150 Гбайт, 10 000 об/хв, кеш 16 Мбайт, SATA/150
    DVD-ROM Samsung SH-S183
    Відеокарта Zotac GeForce 8800 GTS, GPU: GeForce 8800 GTS (500 МГц), пам'ять: 320 Мбайт GDDR3 (1600 МГц)
    Звукова карта Вбудована
    Блок живлення Enermax EG565P-VE, ATX 2.01, 510 Вт
    Системне ПЗ та драйвери
    ОС Windows XP Professional 5.10.2600, Service Pack 2
    Версія DirectX 9.0c (4.09.0000.0904)
    Драйвери платформи Intel Version 8.3.1013
    Графічний драйвер nVidia Forceware 162.18

    Тести та налаштування

    3D-ігри
    Call Of Duty 2 Version: 1.3 Retail
    Video Mode: 1280x960
    Anti Aliasing: off
    Graphics Card: medium
    Timedemo demo2
    Prey Version: 1.3
    Video Mode: 1280x1024
    Video Quality: game default
    Vsync = off
    Benchmark: THG-Demo
    Quake 4 Version: 1.2 (Dual-Core Patch)
    Video Mode: 1280x1024
    Video Quality: high
    THG Timedemo waste.map
    timedemo demo8.demo 1 (1 = load textures)
    Аудіо
    Lame MP3 Version 3.98 Beta 5
    Аудіо CD "Термінатор II SE", 53 min
    wave to mp3
    160 kbps
    Відео
    TMPEG 3.0 Express Version: 3.0.4.24 (no Audio)
    fist 5 Minutes DVD Terminator 2 SE (704x576) 16:9
    Multithreading by rendering
    DivX 6.7 Version: 6.6 (4 Logical CPUs)
    Profile: High Definition Profile
    1-pass, 3000 kbit/s
    Encoding mode: Insane Quality
    Оптимальний multithreading
    no Audio
    XviD 1.1.3 Version: 1.1.3
    Target quantizer: 1.00
    Mainconcept H.264 v2 Version 2.1
    260 MB MPEG-2 source (1920x1080) 16:9
    Код: H.264
    Mode: NTSC
    Audio: AAC
    Profile: High
    Stream: Program
    Програми
    WinRAR Version 3.70
    (303 MB, 47 Files, 2 Folders)
    Compression = Best
    Dictionary = 4096 kB
    Autodesk 3D Studio Max Version: 8.0
    Characters "Dragon_Charater_rig"
    rendering HTDV 1920x1080
    Cinebench Version: R10
    1 CPU, x CPU run
    PCMark05 Pro Version: 1.2.0
    CPU та Memory Tests
    Windows Media Player 10.00.00.3646
    Windows Media Encoder 9.00.00.2980




    Висновок

    Якщо обсяг кеш-пам'яті обмежено впливає такі синтетичні тести, як PCMark05, то різниця у продуктивності більшості реальних додатків виявилася дуже істотною. Спочатку це здається дивним, оскільки досвід каже, що саме синтетичні тести дають найвідчутнішу різницю у продуктивності, яка мало відбивається на реальних додатках.

    Відповідь проста: розмір кешу дуже важливий для сучасних процесорів з мікроархітектурою Core 2 Duo. Ми використовували 4-Мбайт Core 2 Extreme X6800, 2-Мбайт Core 2 Duo E4400 та Pentium Dual Core E2160, який є процесором Core 2 Duo з кешем L2 всього 1 Мбайт. Всі процесори працювали на однаковій системній шині 266 МГц і з множником 9x, щоб частота становила 2400 МГц. Єдина різниця полягає у розмірі кешу, оскільки всі сучасні двоядерні процесори, за винятком старого Pentium D, виготовляються з однакових кристалів. Чим стане ядро, Core 2 Extreme Edition чи Pentium Dual Core, визначається виходом придатних кристалів (дефектами) чи попитом ринку.

    Якщо ви порівняєте результати 3D-шутерів Prey і Quake 4, що є типовими ігровими програмами, різниця у продуктивності між 1 і 4 Мбайт становить приблизно один крок за частотою. Те саме стосується тестів кодування відео для кодеків DivX 6.6 і XviD 1.1.2, а також архіватора WinRAR 3.7. Однак, такі інтенсивно навантажувальні CPU програми, як 3DStudio Max 8, Lame MP3 Encoder або H.264 Encoder V2 від MainConcept не надто сильно виграють від збільшення розміру кешу.

    Втім, підхід Intel, а саме використання всього доступного бюджету транзисторів, який збільшився при переході з 65-нм техпроцесу на 45-нм, має для мікро-архітектури Core 2 Duo певну значимість. Кеш L2 у цих процесорів працює дуже ефективно, особливо якщо врахувати, що він загальний для двох ядер. Тому кеш нівелює вплив різних частот пам'яті та запобігає "вузькому місцем" у вигляді FSB. І робить він це чудово, оскільки тести наочно показують, що продуктивність процесора з одним мегабайтом кеш-пам'яті невисока.

    З цієї точки зору збільшення розміру кешу L2 з 4 Мбайт до максимум 6 Мбайт у майбутніх 45-нм двоядерних процесорів Penryn (лінійка Core 2 Duo E8000) має сенс. Зменшення техпроцесу з 65 до 45 нм дозволяє Intel збільшити бюджет транзисторів, і завдяки збільшенню обсягу кешу ми знову отримаємо зростання продуктивності. Втім, Intel отримає вигоду через різні варіанти процесорів з 6, 4, 2 або навіть 1 Мбайт кешу L2. Завдяки кільком варіантам Intel може використовувати більше кристалів з пластини, незважаючи на наявність випадкових дефектів, які в іншому випадку призводили б до попадання кристала в кошик для сміття. Великий розмір кешу, як бачимо, важливий як для продуктивності, а й у прибутку Intel.

    Всім користувачам добре відомі такі елементи комп'ютера, як процесор, що відповідає за обробку даних, а також оперативна пам'ять (ОЗУ або RAM), що відповідає за їхнє зберігання. Але далеко не всі, напевно, знають, що існує і кеш-пам'ять процесора (Cache CPU), тобто оперативна пам'ять самого процесора (так звана супероперативна пам'ять).

    У чому полягає причина, яка спонукала розробників комп'ютерів використовувати спеціальну пам'ять для процесора? Чи можливостей ОЗУ для комп'ютера недостатньо?

    Дійсно, довгий час персональні комп'ютери обходилися без кеш-пам'яті. Але, як відомо, процесор – це найшвидший пристрій персонального комп'ютера і його швидкість зростала з кожним новим поколінням CPU. Нині його швидкість вимірюється мільярдами операцій на секунду. У той самий час стандартна оперативна пам'ять менш значно збільшила свою швидкодію під час своєї еволюції.

    Взагалі, існують дві основні технології мікросхем пам'яті – статична пам'ять та динамічна пам'ять. Не заглиблюючись у подробиці їх устрою, скажемо лише, що статична пам'ять, на відміну динамічної, вимагає регенерації; крім того, у статичній пам'яті для одного біта інформації використовується 4-8 транзисторів, у той час як у динамічній – 1-2 транзистори. Відповідно динамічна пам'ять набагато дешевша статичної, але в той же час і набагато повільніша. Нині мікросхеми ОЗУ виготовляються з урахуванням динамічної пам'яті.

    Зразкова еволюція співвідношення швидкості роботи процесорів та ОЗП:

    Таким чином, якби процесор брав весь час інформацію з оперативної пам'яті, то йому довелося б чекати повільну динамічну пам'ять, і він весь час простоював. У тому випадку, якби як ОЗУ використовувалася статична пам'ять, то вартість комп'ютера зросла б у кілька разів.

    Саме тому було розроблено розумний компроміс. Основна частина ОЗП так і залишилася динамічною, у той час як у процесора з'явилася своя швидка кеш-пам'ять, заснована на мікросхем статичної пам'яті. Її обсяг порівняно невеликий – наприклад, обсяг кеш-пам'яті другого рівня становить лише кілька мегабайт. Втім, тут варто згадати, що вся оперативна пам'ять перших комп'ютерів IBM PC становила менше 1 МБ.

    Крім того, на доцільність впровадження технології кешування впливає ще й той фактор, що різні програми, що знаходяться в оперативній пам'яті, по-різному навантажують процесор, і, як наслідок, існує чимало даних, які потребують пріоритетної обробки порівняно з іншими.

    Історія кеш-пам'яті

    До того, як кеш-пам'ять перебралася на персоналки, вона вже кілька десятиліть успішно використовувалася в суперкомп'ютерах.

    Вперше кеш-пам'ять обсягом всього 16 КБ з'явилася в ПК на базі процесора i80386. Сьогодні сучасні процесори використовують різні рівні кешу, від першого (найшвидший кеш найменшого обсягу – зазвичай, 128 КБ) до третього (найповільніший кеш найбільшого обсягу – до десятків МБ).

    Спочатку зовнішня кеш-пам'ять процесора розміщалася окремому чіпі. Згодом, однак, це призвело до того, що шина, розташована між кешем і процесором, стала вузьким місцем, що уповільнює обмін даними. У сучасних мікропроцесорах і перший, і другий рівні кеш-пам'яті знаходяться у самому ядрі процесора.

    Довгий час у процесорах існувало лише два рівні кешу, але в CPU Intel Itanium вперше з'явилася кеш-пам'ять третього рівня, загальна для всіх ядер процесора. Існують і розробки процесорів із чотирирівневим кешем.

    Архітектури та принципи роботи кешу

    На сьогоднішній день відомі два основні типи організації кеш-пам'яті, які беруть свій початок від перших теоретичних розробок у галузі кібернетики – принстонська та гарвардська архітектури. Принстонська архітектура має на увазі єдине місце пам'яті для зберігання даних і команд, а гарвардська - роздільне. Більшість процесорів персональних комп'ютерів лінійки x86 використовують окремий тип кеш-пам'яті. Крім того, у сучасних процесорах з'явився також третій тип кеш-пам'яті – так званий буфер асоціативної трансляції, призначений для прискорення перетворення адрес віртуальної пам'яті операційної системи на адреси фізичної пам'яті.

    Спрощено схему взаємодії кеш-пам'яті та процесора можна описати так. Спочатку відбувається перевірка наявності потрібної процесору інформації в найшвидшому – кеші першого рівня, потім – у кеші другого рівня, і.т.д. Якщо ж потрібної інформації в якомусь рівні кешу не виявилося, то говорять про помилку, або промах кеша. Якщо інформації в кеші немає взагалі, то процесору доводиться брати її із ОЗУ або навіть із зовнішньої пам'яті (з жорсткого диска).

    Порядок пошуку процесором інформації у пам'яті:

    Саме таким чином процесор здійснює пошук інформації

    Для керування роботою кеш-пам'яті та її взаємодії з обчислювальними блоками процесора, а також ОЗУ існує спеціальний контролер.

    Схема організації взаємодії ядра процесора, кешу та ОЗП:

    Кеш-контролер є ключовим елементом зв'язку процесора, ОЗУ та Кеш-пам'яті

    Слід зазначити, що кешування даних – це складний процес, у ході якого використовують безліч технологій і математичних алгоритмів. Серед базових понять, що застосовуються під час кешування, можна виділити методи запису кешу та архітектуру асоціативності кеш-пам'яті.

    Методи запису кешу

    Існує два основних методи запису інформації в кеш-пам'ять:

    1. Метод write-back (зворотний запис) - запис даних проводиться спочатку в кеш, а потім, при настанні певних умов, та в ОЗУ.
    2. Метод write-through (наскрізний запис) - запис даних проводиться одночасно в ОЗУ та в кеш.

    Архітектура асоціативності кеш-пам'яті

    Архітектура асоціативності кешу визначає спосіб, з якого дані з ОЗУ відображаються в кеші. Існують такі основні варіанти архітектури асоціативності кешування:

    1. Кеш із прямим відображенням – певна ділянка кешу відповідає за певну ділянку ОЗУ
    2. Повністю асоціативний кеш – будь-яка ділянка кешу може асоціюватись з будь-якою ділянкою ОЗУ
    3. Змішаний кеш (набірно-асоціативний)

    На різних рівнях кешу зазвичай можна використовувати різні архітектури асоціативності кеша. Кешування з прямим відображенням ОЗУ є найшвидшим варіантом кешування, тому ця архітектура зазвичай використовується для великих кешів. У свою чергу, повністю асоціативний кеш має меншу кількість помилок кешування (промахів).

    Висновок

    У цій статті ви познайомилися з поняттям кеш-пам'яті, архітектурою кеш-пам'яті та методами кешування, дізнались, як вона впливає на продуктивність сучасного комп'ютера. Наявність кеш-пам'яті дозволяє значно оптимізувати роботу процесора, зменшити час його простою, а отже, і збільшити швидкодію всієї системи.

    Усі процесори з кінця 90-х років мають внутрішню кеш-пам'ять (або кеш). Кеш - це швидкодіюча пам'ять, в яку переносяться команди та дані, що безпосередньо обробляються процесором.

    У сучасних процесорах вбудована кеш-пам'ять двох рівнів – першого (L1) та другого (L2). З вмістом кешу L1 процесор працює дещо швидше, а об'єм кешу L2 зазвичай дещо більший. Звернення до кеш-пам'яті відбувається стан очікування, тобто. кеш-пам'ять першого рівня (вбудований кеш) працює на частоті процесора.

    Це означає, якщо дані, необхідні процесору, перебувають у кеш-пам'яті, то затримок з обробкою немає. В іншому випадку процесор повинен отримати дані з основної пам'яті, що суттєво зменшує швидкодію системи.

    Щоб якісно розібратися з принципом роботи кешпам'яті обох рівнів, розглянемо з прикладу побутову ситуацію.

    Ви приходите в кафе пообідати щодня, в один і той же час, і сідайте завжди за один і той самий столик. Завжди замовляєте стандартний набір із трьох страв.

    Офіціант бігає на кухню, кухар їх розкладає на тацю і потім вам приносять замовлення. І ось, скажімо, на третій день офіціант, щоб зайвий раз не бігати на кухню, до призначеного часу зустрічає вас із готовим гарячим обідом на підносі.

    Ви не чекаєте на замовлення і заощадили масу часу. Піднос із вашими стравами – це і є кеш першого рівня. Але на четвертий день вам раптом захотілося додати ще одну страву, скажімо, десерт.

    Хоча на вас у призначений час уже чекав піднос із замовленням, але за десертом офіціантові все одно довелося бігти на кухню.

    А на п'ятий — знову меню із трьох найменувань. На шостий знову десерт, але відрізняється від попереднього. І офіціант, не знаючи, що ви з десерту захочете замовити (та й взагалі не знаючи, чи будете ви щось замовляти), вирішується на наступний крок: поряд з вашим столиком ставить шафку з декількома найменуваннями десерту.

    І якщо ви виявите бажання, все під рукою, на кухню бігти не треба. Шафка з десертом - це кеш другого рівня.

    Від обсягу кешу L1 (від 16 до 128 Кбайт) та L2 (від 64 Кбайт до 512 Кбайт, у Pentium III Хеоп та AMD Opteron до 4 Мбайт) істотно залежить продуктивність процесора.

    У процесорів Intel Pentium III та процесорів Celeron на його основі розмір кешу L1 становить 32 Кбайт. Intel Pentium 4, а також на його базі Celeron і Хеоп-версій — всього 20 Кбайт. Процесори AMD Duron, Athlon (включаючи ХР/МР) та Opteron, а також VIA СЗ містять 128 Кбайт L1 кешу.

    Сучасні двоядерні процесори мають кеш першого рівня кожного ядра окремо, тому іноді в описі кешу ми можемо зустріти цифру 128×2. Це означає, що кожне ядро ​​процесора має 128 Кбайт кеш-пам'яті першого рівня.

    Розмір кешу L1 важливий для отримання високої продуктивності у більшості поширених завдань (офісні програми, ігри, більшість серверних програм тощо). Особливо сильно його ефективність проявляється для потокових обчислень (наприклад обробка відеозображення).

    Це одна з причин того, що Pentium 4 є відносно малоефективним для більшості поширених застосувань (хоча це компенсується високою тактовою частотою). Кеш L1 завжди працює (обмінюється інформацією з ядром процесора) на внутрішній частоті процесора.

    На відміну від нього, кеш L2 у різних моделях процесорів працює з різною частотою (і відповідно продуктивністю). Починаючи з Intel Pentium II у багатьох процесорах застосовувався кеш L2, що працює на частоті, наполовину меншій, ніж внутрішня частота процесора.

    Таке рішення використано в застарілих процесорах Intel Pentium III (до 550 МГц) та застарілих AMD Athlon (у деяких із них внутрішній кеш L2 працював на третині частоти ядра процесора). Об'єм кешу L2 також різний для різних процесорів.

    У застарілих, а також деяких нових процесорах Intel Pentium III обсяг кешу L2 становить 512 Кбайт, в інших Pentium III - 256 Кбайт. Процесор Intel Celeron на основі Pentium III випускався зі 128 і 256 Кбайт кешу L2, а на основі Pentium 4 – лише зі 128 Кбайт. У різних варіантах Xeon-версії Intel Pentium 4 є до 4 Мбайт кеш-пам'яті L2.

    У нових процесорах Pentium 4 (деякі серії з частотою 2000 МГц і всі – для частот вище) є 512 Кбайт кешу L2, у решті Pentium 4 -256 Кбайт. У процесорах Хеоп (з урахуванням Pentium 4) буває 256 чи 512 Кбайт кешу L2.

    Крім того, в них є ще кеш-пам'ять третього рівня L3. Інтегрована кеш-пам'ять L3 у поєднанні зі швидкою системною шиною формує високошвидкісний канал обміну даними із системною пам'яттю.

    Як правило, кеш-пам'яттю третього рівня L3 комплектуються лише процесори для серверних рішень або спеціальні моделі настільних процесорів. Кеш-пам'яттю L3 мають, наприклад, такі лінійки процесорів, як Xeon DP, Itanium 2, Xeon MP.

    Процесор AMD Duron має 128 Кбайт кешу L1 та 64 Кбайт кешу L2. У процесорах Athlon (крім найстаріших), Athlon MP і більшості варіантів Athlon ХР присутній 128 Кбайт кешу L1 і 256 Кбайт кешу L2, а новітніх Athlon ХР (2500+, 2800+, 3000+ і ша) — 51 AMD Opteron містить 1 Мбайт кеш-пам'яті L2.

    Останні моделі процесорів Intel Pentium D, Intel Pentium M, Intel Core 2 Duo випускаються з 6 Мбайт кеш-пам'яті L2, а Core 2 Quad – 12 Мбайт кеш-пам'яті L2.

    Останній на момент написання цієї книги процесор фірми Intel Core i7 має 64 Кбайт кеш-пам'яті L1 для кожного з 4 ядер, а також 256 Кбайт пам'яті L2 для кожного ядра. Крім кеш пам'яті першого та другого рівнів процесор має і загальну для всіх ядер кеш-пам'ять третього рівня, що дорівнює 8 Мбайт.

    Для процесорів, у яких можливий різний розмір кешу L2 (або Intel Xeon MP - L3) в однієї і тієї ж моделі, цей розмір повинен бути вказаний при продажі (від нього, зрозуміло, залежить ціна процесора). Якщо процесор продається в "коробковій" упаковці (постачання In-Box), на ній зазвичай вказується розмір кеш-пам'яті.

    Для звичайних завдань користувача (у тому числі ігор) важливіше швидкість кешу L2, ніж його обсяг; для серверних завдань, навпаки, важливішим є обсяг. Найбільш продуктивні сервери, особливо з великим обсягом оперативної пам'яті (кілька гігабайт), потребують максимального обсягу та максимальної швидкості кешу L2.

    Неперевершеними за цими параметрами залишаються Хеоп-версії процесорів Pentium III. (Процесор Xeon MP виявляється все ж таки більш продуктивні в серверних задачах, ніж Pentium III Xeon, за рахунок вищої тактової частоти самого процесора і шини обміну інформацією з пам'яттю.) З викладеного вище зробимо висновок: кеш-пам'ять покращує взаємодію між швидким процесором і більше повільною оперативною пам'яттю, а також дозволяє мінімізувати періоди очікування, що виникають під час обробки даних. Вирішальну роль цьому грає кеш-пам'ять другого рівня, розташована в кристалі процесора.

    Майже всі розробники знають, що кеш процесора - це така маленька, але швидка пам'ять, в якій зберігаються дані з нещодавно відвіданих областей пам'яті - коротке визначення і досить точне. Тим не менш, знання «нудних» подробиць щодо механізмів роботи кешу необхідне для розуміння факторів, що впливають на продуктивність коду.

    У цій статті ми розглянемо ряд прикладів, що ілюструють різні особливості роботи кешів та їх вплив на продуктивність. Приклади будуть на C#, вибір мови та платформи не так сильно впливає на оцінку продуктивності та кінцеві висновки. Природно, в розумних межах, якщо ви оберете мову, в якій читання значення з масиву рівносильне зверненню до хеш-таблиці, жодних результатів придатних до інтерпретації ви не отримаєте. Курсивом йдуть зауваження перекладача.

    Habracut - - -

    Приклад 1: доступ до пам'яті та продуктивність

    Як ви думаєте, наскільки другий цикл швидше за перший?
    int arr = new int;

    // перший
    for (int i = 0; i< arr.Length; i++) arr[i] *= 3;

    // другий
    for (int i = 0; i< arr.Length; i += 16) arr[i] *= 3;


    Перший цикл множить всі значення масиву на 3, другий цикл лише кожне шістнадцяте значення. Другий цикл здійснює тільки 6% роботипершого циклу, але на сучасних машинах обидва цикли виконуються приблизно за рівний час: 80 мсі 78 мсвідповідно (на моїй машині).

    Розгадка проста – доступ до пам'яті. Швидкість роботи цих циклів насамперед визначається швидкістю роботи підсистеми пам'яті, а чи не швидкістю цілочисленного множення. Як ми побачимо в наступному прикладі, кількість звернень до оперативної пам'яті однакова і в першому та другому випадку.

    Приклад 2: вплив рядків кешу

    Копнем глибше - спробуємо інші значення кроку, не тільки 1 і 16:
    for (int i = 0; i< arr.Length; i += K /* шаг */ ) arr[i] *= 3;

    Ось час роботи цього циклу для різних значень кроку K:

    Зверніть увагу, що при значеннях кроку від 1 до 16 час роботи практично не змінюється. Але при значеннях більше 16, час роботи зменшується приблизно вдвічі щоразу, коли ми збільшуємо крок у два рази. Не означає, що цикл якимось магічним чином починає працювати швидше, просто кількість ітерацій у своїй так само зменшується. Ключовий момент – однаковий час роботи при значеннях кроку від 1 до 16.

    Причина цього в тому, що сучасні процесори здійснюють доступ до пам'яті не побайтно, а невеликими блоками, які називають рядками кешу. Зазвичай розмір рядка становить 64 байти. Коли ви читаєте якесь значення з пам'яті, у кеш потрапляє щонайменше один рядок кеша. Подальший доступ до якогось значення з цього рядка відбувається дуже швидко.

    Через те, що 16 значень типу int займають 64 байти, цикли з кроками від 1 до 16 звертаються до однакової кількості рядків кешу, точніше, до всіх рядків кешу масиву. При кроці 32 звернення відбувається до кожного другого рядка, при кроці 64, до кожного четвертого.

    Розуміння цього дуже важливе для деяких способів оптимізації. Від місця розташування даних у пам'яті залежить кількість звернень до неї. Наприклад, через невирівняні дані може знадобитися два звернення до оперативної пам'яті, замість одного. Як ми з'ясували вище, швидкість роботи при цьому буде вдвічі нижчою.

    Приклад 3: розміри кешів першого та другого рівня (L1 та L2)

    Сучасні процесори, як правило, мають два або три рівні кешів, зазвичай їх називають L1, L2 та L3. Щоб дізнатися розміри кешів різних рівнів, можна скористатися утилітою CoreInfo або функцією Windows API GetLogicalProcessorInfo . Обидва способи також надають інформацію про розмір рядка кешу для кожного рівня.

    На моїй машині CoreInfo повідомляє про кеші даних L1 об'ємом по 32 Кбайт, кеші інструкцій L1 об'ємом по 32 Кбайт і кеші даних L2 об'ємом по 4 Мбайт. Кожне ядро ​​має свої персональні кеші L1, кеші L2 спільні для кожної пари ядер:

    Logical Processor to Cache Map: *--- Data Cache 0, Level 1, 32 KB, Assoc 8, LineSize 64 *--- Instruction Cache 0, Level 1, 32 KB, Assoc 8, LineSize 64 -*-- Data Cache 1, Level 1, 32 KB, Assoc 8, LineSize 64 -*-- Instruction Cache 1, Level 1, 32 KB, Assoc 8, LineSize 64 **-- Unified Cache 0, Level 2, 4 MB, Assoc 16, LineSize 64 --*- Data Cache 2, Level 1, 32 KB, Assoc 8, LineSize 64 --*- Instruction Cache 2, Level 1, 32 KB, Assoc 8, LineSize 64 ---* Data Cache 3, Level 1, 32 KB, Assoc 8, LineSize 64 ---* Instruction Cache 3, Level 1, 32 KB, Assoc 8, LineSize 64 --** Unified Cache 1, Level 2, 4 MB, Assoc 16, LineSize 64
    Перевіримо цю інформацію експериментально. Для цього пройдемося по нашому масиву інкрементуючи кожне 16-е значення - простий спосіб змінити дані в кожному рядку кешу. При досягненні кінця повертаємося до початку. Перевіримо різні розміри масиву, ми повинні побачити падіння продуктивності, коли масив перестає поміщатися в кеші різних рівнів.

    Код такий:

    int steps = 64*1024*1024; // кількість ітерацій
    int lengthMod = arr.Length - 1; // розмір масиву - ступінь двійки

    for (int i = 0; i< steps; i++)
    {
    // x & lengthMod = x % arr.Length, бо ступеня двійки
    arr [(i * 16) & lengthMod] ++;
    }


    Результати тестів:

    На моїй машині помітні падіння продуктивності після 32 Кбайт та 4 Мбайт – це і є розміри кешів L1 та L2.

    Приклад 4: паралелізм інструкцій

    Тепер погляньмо на дещо інше. На вашу думку, який із цих двох циклів виконається швидше?
    int steps = 256*1024*1024;
    int a = new int;

    // перший
    for (int i = 0; i< steps; i++) { a++; a++; }

    // другий
    for (int i = 0; i< steps; i++) { a++; a++; }


    Виявляється, другий цикл виконується майже вдвічі швидше, принаймні на всіх протестованих мною машинах. Чому? Тому що команди усередині циклів мають різні залежності за даними. Команди першого мають наступний ланцюжок залежностей:

    У другому циклі залежності такі:

    Функціональні частини сучасних процесорів здатні виконувати певну кількість деяких операцій одночасно, зазвичай, невелике число. Наприклад, можливий паралельний доступ до даних з кешу L1 за двома адресами, так само можливе одночасне виконання двох простих арифметичних команд. У першому циклі процесор неспроможна задіяти ці можливості, а може у другому.

    Приклад 5: асоціативність кешу

    Одне з ключових питань, на яке необхідно дати відповідь при проектуванні кешу - чи можуть дані з певної області пам'яті зберігатися в будь-яких осередках кешу або лише в деяких із них. Три можливі рішення:
    1. Кеш прямого відображення, дані кожного рядка кешу в оперативній пам'яті зберігаються лише в одному заздалегідь визначеному осередку кешу. Найпростіший спосіб обчислення відображення: індекс_рядка_в_пам'яті % кількість_осередків_кешу. Два рядки, відображені на один і той же осередок, не можуть знаходитися в кеші одночасно.
    2. N-вхідний частково-асоціативний кеш, кожен рядок може зберігатися в N різних осередках кешу. Наприклад, у 16-входовому кеші рядок може зберігатися в одному з 16-ти осередків складових групу. Зазвичай рядки з рівними молодшими бітами індексів поділяють одну групу.
    3. Повністю асоціативний кеш, будь-який рядок може бути збережено в будь-яку комірку кешу. Рішення еквівалентне хеш-таблиці за своєю поведінкою.
    Кеші прямого відображення схильні до конфліктів, наприклад, коли два рядки змагаються за один осередок, по черзі витісняючи один одного з кеша, ефективність дуже низька. З іншого боку, повністю асоціативні кеші, хоч і позбавлені цього недоліку, дуже складні та дорогі у реалізації. Частково-асоціативні кеші – типовий компроміс між складністю реалізації та ефективністю.

    Наприклад, на моїй машині кеш L2 розміром 4 Мбайт є 16-входовим частково-асоціативним кешем. Вся оперативна пам'ять розділена на безліч рядків по молодшим бітам їх індексів, рядки з кожної множини змагаються за одну групу з 16 осередків кешу L2.

    Так як кеш L2 має 65536 осередків (4 * 2 20 / 64) і кожна група складається з 16 осередків, всього ми маємо 4096 груп. Таким чином, молодші 12 біт індексу рядка визначають до якої групи відноситься цей рядок (2 12 = 4 096). У результаті рядки з адресами кратними 262 144 (4 096 * 64) поділяють ту саму групу з 16-ти осередків і змагаються за місце в ній.

    Щоб ефекти асоціативності проявили себе, нам необхідно постійно звертатися до великої кількості рядків з однієї групи, наприклад, використовуючи наступний код:

    public static long UpdateEveryKthByte(byte arr, int K)
    {
    const int rep = 1024*1024; // кількість ітерацій

    Stopwatch sw = Stopwatch.StartNew();

    int p = 0;
    for (int i = 0; i< rep; i++)
    {
    arr[p]++;

    P + = K; if (p> = arr.Length) p = 0;
    }

    Sw.Stop();
    return sw.ElapsedMilliseconds;
    }


    Метод інкрементує кожен K-ий елемент масиву. Після досягнення кінця, починаємо заново. Після досить великої кількості ітерацій (220), зупиняємося. Я зробив прогони для різних розмірів масиву та значень кроку K. Результати (синій – великий час роботи, білий – маленький):

    Синім областям відповідають ті випадки, коли при постійній зміні даних кеш не вміє вмістити всі необхідні дані одночасно. Яскравий синій колір говорить про час роботи близько 80 мс, майже білий – 10 мс.

    Розберемося із синіми областями:

    1. Чому з'являються вертикальні лінії?Вертикальні лінії відповідають значенням кроку, при яких здійснюється доступ до занадто великого числа рядків (більше 16-ти) з однієї групи. Для таких значень 16-вхідний кеш моєї машини не може вмістити всі необхідні дані.

      Деякі з поганих значень кроку - ступеня двійки: 256 і 512. Наприклад розглянемо крок 512 і масив 8 Мбайт. При цьому кроці в масиві є 32 ділянки (8 * 2 20 / 262 144), які ведуть боротьбу один з одним за осередки в 512 групах кешу (262 144 / 512). Ділянки 32, а осередків у кеші під кожну групу лише 16, тому місця на всіх не вистачає.

      Інші значення кроку, що не є ступенями двійки, просто невдачливі, що викликає велику кількість звернень до однакових груп кешу, а також призводить до появи вертикальних синіх ліній на малюнку. На цьому місці любителям теорії чисел пропонується замислитись.

    2. Чому вертикальні лінії обриваються на кордоні 4 Мбайт?При розмірі масиву в 4 Мбайт або менше, 16-вхідний кеш поводиться так само, як і повністю асоціативний, тобто може вмістити всі дані масиву без конфліктів. Є трохи більше 16-ти областей провідних боротьбу одну групу кешу (262 144 * 16 = 4 * 2 20 = 4 Мбайт).
    3. Чому зліва нагорі знаходиться великий синій трикутник?Тому що при невеликому етапі і великому масиві кеш не в змозі вмістити всі необхідні дані. Ступінь асоціативності кеша відіграє тут другорядну роль, обмеження пов'язані з обсягом кешу L2.

      Наприклад, при розмірі масиву в 16 Мбайт і кроці 128, ми звертаємося до кожного 128 байта, таким чином, модифікуючи кожен другий рядок кешу масиву. Щоб зберегти кожен другий рядок у кеші, необхідний його об'єм 8 Мбайт, але на моїй машині є лише 4 Мбайт.

      Навіть якби кеш був повністю асоціативним, це не дозволило б зберегти в ньому 8 Мбайт даних. Зауважте, що у вже розглянутому прикладі з кроком 512 та розміром масиву 8 Мбайт, нам необхідний лише 1 Мбайт кешу, щоб зберегти всі необхідні дані, але це неможливо зробити через недостатню асоціативність кешу.

    4. Чому ліва сторона трикутника поступово набирає своєї інтенсивності?Максимум інтенсивності посідає значення кроку 64 байти, що дорівнює розміру рядка кеша. Як ми побачили в першому і в другому прикладі, послідовний доступ до одного і того ж рядка практично нічого не вартий. Скажімо, при кроці 16 байт, ми маємо чотири звернення до пам'яті за ціною одного.

      Так як кількість ітерацій дорівнює в нашому тесті за будь-якого значення кроку, то більш дешевий крок в результаті дає менший час роботи.

    Виявлені ефекти зберігаються при великих значеннях параметрів:

    Асоціативність кешу – цікава штука, яка може проявити себе за певних умов. На відміну від інших розглянутих у цій статті проблем, вона не є такою серйозною. Безперечно, це не те, що вимагає постійної уваги при написанні програм.

    Приклад 6: хибний поділ кешу

    На багатоядерних машинах можна зіткнутися з іншою проблемою – узгодження кешів. Ядра процесора мають частково чи повністю роздільні кеші. На моїй машині кеші L1 роздільні (як і зазвичай), так само є два кеші L2, спільні для кожної пари ядер. Деталі можуть відрізнятися, але загалом сучасні багатоядерні процесори мають багаторівневі ієрархічні кеші. Причому найшвидші, але й найменші кеші належать індивідуальним ядрам.

    Коли одне з ядер модифікує значення у своєму кеші, інші ядра більше неможливо використовувати старе значення. Значення в кешах інших ядер має бути оновлено. Більше того, має бути оновлена повністю весь рядок кешу, тому що кеші оперують даними на рівні рядків.

    Продемонструємо цю проблему на наступному коді:

    private static int s_counter = new int;

    private void UpdateCounter(int position)
    {
    for (int j = 0; j< 100000000; j++)
    {
    s_counter = s_counter + 3;
    }
    }


    Якщо на своїй чотириядерній машині я викличу цей метод із параметрами 0, 1, 2, 3 одночасно з чотирьох потоків, то час роботи становитиме 4.3 секунди. Але якщо я викликаю метод із параметрами 16, 32, 48, 64, то час роботи становитиме лише 0.28 секунд.

    Чому? У першому випадку всі чотири значення, оброблювані потоками в кожен момент часу, з великою ймовірністю потрапляють в один рядок кеша. Щоразу, коли одне ядро ​​збільшує чергове значення, воно позначає осередки кешу, що містять це значення в інших ядрах, як невалідні. Після цієї операції всі інші ядра повинні будуть закешувати рядок заново. Це робить механізм кешування непрацездатним, вбиваючи продуктивність.

    Приклад 7: складність заліза

    Навіть тепер, коли принципи роботи кешів для вас не секрет, залізо, як і раніше, дасть вам сюрпризи. Процесори відрізняються один від одного методами оптимізації, евристиками та іншими тонкощами реалізації.

    Кеш L1 деяких процесорів може здійснювати паралельний доступ до двох осередків, якщо вони відносяться до різних груп, але якщо вони відносяться до однієї, тільки послідовно. Наскільки мені відомо, деякі навіть можуть здійснювати паралельний доступ до різних четвертинок одного осередку.

    Процесори можуть здивувати вас хитрими оптимізаціями. Наприклад, код з попереднього прикладу про помилковий поділ кешу не працює на моєму домашньому комп'ютері так, як замислювалося - у найпростіших випадках процесор може оптимізувати роботу та зменшити негативні ефекти. Якщо код трохи модифікувати, все стає на свої місця.

    Ось інший приклад дивних примх заліза:

    private static int A, B, C, D, E, F, G;

    private static void Weirdness()
    {
    for (int i = 0; i< 200000000; i++)
    {
    <какой-то код>
    }
    }


    Якщо замість<какой-то код>підставити три різні варіанти, можна отримати такі результати:

    Інкрементування полів A, B, C, D займає більше часу, ніж інкрементування полів A, C, E, G. Що ще дивніше, інкрементування полів A та C займає більше часу, ніж полів A, C і E, G. Не знаю точно які причини цього, але можливо вони пов'язані з банками пам'яті ( так-так, із звичайними трилітровими ощадними банками пам'яті, а не те, що ви подумали). Тих, хто має міркування щодо цього, прошу висловлюватися в коментарях.

    У мене на машині вищеописаного не спостерігається, проте іноді бувають аномально погані результати - швидше за все, планувальник завдань вносить свої «корективи».

    З цього прикладу можна винести наступний урок: дуже складно передбачити поведінку заліза. Так, можна, можливопередбачити багато, але необхідно постійно підтверджувати свої передбачення за допомогою вимірів та тестування.

    Висновок

    Сподіваюся, що все розглянуте допомогло зрозуміти пристрій кешів процесорів. Тепер ви можете використовувати знання на практиці для оптимізації свого коду.