Програмне кешування

На тему: Програмне кешування

2. Програмна передвиборка у процесорах К6+ та РIII+.

3. Передвиборка у процесорах AMD К6 та VIA C3.

4. Передвиборка у процесорах РIIIі Р4.

7. Ефективність передвиборки у багатозадачних системах.

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

До того часу, поки більшість додатків перемелювали компактні, багаторазово оброблювані структури даних, стратегія завантаження кеш-лінійок на першу вимогу справлялася зі своїм завданням, але з появою мультимедійних додатків стала "буксувати". Різко зрослий обсяг оброблюваних даних і поширення потокових алгоритмів, що звертаються до кожної осередку пам'яті лише один раз, обернувся постійними перезавантаженнями кешу, що обмежило продуктивність системи не швидкодією процесора, а пропускною здатністю оперативної пам'яті. Вперше цю проблему кинула виклик фірма AMD, включивши до складу набору команд 3DNow! інструкцію prefetch, що дозволяє програмісту заздалегідь завантажувати в кеш осередки пам'яті, до яких він розраховує звернутись у найближчому майбутньому. Причому завантаження даних здійснюється без участі та зупинення обчислювального конвеєра! Це вбиває двох зайців відразу: по-перше, ручне управління кеш-контролером дозволяє вибрати оптимальну стратегію запобіжного завантаження даних, що суттєво зменшує кількість кеш-промахів, а, по-друге, з передвиборкою стає можливим завантажувати чергову порцію даних паралельно з обробкою попередньої, маскуючи тим самим латентність оперативної пам'яті.

Слідом за К6, передвиборка (природно у вдосконаленому варіанті) з'явилася і в Pentiumlll, та не одна, а з цілим почетом команд ручного управління кешуванням - Intel явно не хотіла відставати від конкурентів!

Програмна передвиборка в процесорах К6+ та РIII+

Підтримка програмної передвиборки є як у К6/К7 (і сумісному з К6 мікропроцесорі VIAC3), і у Р. /Р4, проте, їх реалізації різні і ще сумісні друг з одним. Процесори від AMD (VIA) не розуміють інструкцій передвиборки процесорів Intel і, навпаки.

Ця сумна обставина істотно знижує популярність передвиборки, оскільки програмістам доводиться або писати два варіанти коду: один Intel, інший для AMD(VIA); або обмежувати аудиторію користувачів одним із процесорів.

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

Передвиборчка в процесорах AMD К6 і VIA C3

У К6/К7 та VIAC3 програмна передвиборка здійснюється однією з двох інструкцій: prefetch або prefetchw. Літера w наприкінці останньої повідомляє процесору, що завантажені дані планується модифікувати. Це зовсім не означає, що дані, що завантажуються за допомогою prefetch, не можна модифікувати. Модифікувати їх можна, але не бажано, тому що в цьому випадку процесор змушений здійснювати додатковий цикл,змінюючи атрибути відповідної кеш-лінійки з ексклюзивною на модифіковану.

Інструкція prefetch просто ініціює запит осередку пам'яті, так само, як це робить будь-яка команда, що звертається до пам'яті, але, на відміну від останньої, prefetch не поміщає завантажені дані в жодний регістр, більше того, вона взагалі не чекає кінця завантаження цих даних, відразу повертаючи управління. Передчасне завершення ініціатора запиту ще не звільняє кеш-контролер від обов'язку виконання цього запиту, але якщо запитувана комірка вже знаходиться в кеші першого рівня, нічого не відбувається і інструкція prefetch веде себе аналогічно до команди NOP (немає операції). В іншому випадку кеш-контролер звертається до кешу другого рівня, а якщо шуканого осередку не виявляється і там - до оперативної пам'яті (кешу третього рівня), повністю заповнюючи відповідні кеш-рядки кешів усіх рівнів нижче. Оскільки кеш-контролер працює незалежно від обчислювального конвеєра процесора, вибірка дозволяє завантажувати чергову порцію даних паралельно з обробкою попередньої. Якщо час завантаження даних не перевищує часу їх обробки, то простою процесора взагалі не відбувається - обчислювальний конвеєр працює безупинно, а час доступу до пам'яті повністю маскується.

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

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

Незважаючи на те, що AMD позиціонує команди передвиборки як апаратно-незалежні, вони такими не є, оскільки кількість байт, що завантажуються інструкціями prefetch і prefetchw, визначаються розмірами кеш-ліній процесора, а їх довжина різна: 32 байти для AMDK6 (VIAC3) та 64 байта для Athlon/Duron. Відповідно, різні оптимальний крок та мінімальна дистанція передвиборки.

У цьому світлі стає дуже цікавим наступне висловлювання AMD, почерпнуте з посібника з оптимізації під Athlon: "Інструкції PREFETCHNTA/T0/T1/T2 з ММХ-розширення апаратно залежні. Якщо ви, пане розробник, потребуєте сумісності з 25 мільйонами AMD вже продано -K6-2 та AMD-K6-III, замість інструкцій передвиборки нового розширення ММХ, користуйтеся командами PREFETCH/W із розширення 3Dnow!"

Ось гарна демонстрація мистецтва промовчання! Якщо вже кидати камінь у город Intel, то не зайве б відзначити, що, по-перше, і власні інструкції передвиборки апаратно-залежні, а по-друге, процесорами Pentium вони не підтримуються. Так що жодних переваг у AMD `шної передвиборки перед Intel немає.

Передвиборчка в процесорах Р. і Р4

У процесорах Р. і Р4 програмна передвиборка здійснюється наступними інструкціями: prefetchnta, prefetcht0, prefetcht1, prefetcht2. Суфікс вказує на тип даних, що завантажуються, що визначає рівень кеш-ієрархії, в яку ці дані будуть завантажені. Так NTA розшифровується як Non-TemporAl [Data] - не тимчасові дані, тобто. дані, багаторазове використання яких планується. Відповідно Т0, Т1, Т2 позначає тимчасовідані, які планується використовувати неодноразово.

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

Причому на відміну від prefetch/w, інструкції prefetchnta/t0/t1/t2 не наказують, а рекомендують здійснити передвиборку. Процесор відхиляє рекомендацію і не здійснює передвиборку, якщо:

  • запитані дані вже містяться у кеші відповідної чи найближчої до процесора ієрархії;
  • відомості про сторінку, до якої належать дані, що завантажуються, відсутні в DTLB (DataTranslationLookasideBuffer - Буфері Асоціативної Трансляції;)
  • підсистема пам'яті процесора зайнята переміщенням даних між L1-і L2-кешем;
  • запитані дані належать регіону пам'яті, що не кешується (сторінці з атрибутами UC і USWC);
  • дані не можуть бути завантажені через помилку доступу (при цьому виняток не виробляється);
  • інструкція передвиборки випереджається префіксом LOCK (у цьому випадку генерується виняток "невірний опкод");

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

Pentium lll

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