Как стать автором
Обновить

Комментарии 59

SPU — Synergistic Processing Unit, это SIMD ядро процессора Cell. (В контексте статьи упоминается из за того, что имеет свою «бортовую» RAM)
НЛО прилетело и опубликовало эту надпись здесь
Аллё? Ядро у аппарата.
И это не приколы translate.google.com :)
В оригинале: "...typical require descending into the kernel to service the allocation requests..."
вызовов ядра. Оригинала не вижу, но там были kernel calls :-)
Да, лучше было написать «требует системных вызовов» или перевести близко к тексту: «требует переходов на уровень ядра для обработки запросов выделения памяти».
А по-моему, неплохо получилось. Этакий недо-сленг :-)
Как многие, возможно, догадались, мне нравятся переводы, не засушенные книжным языком, особенно если оригинальный автор тоже использует неформальный стиль. Отсюда и «аллокатор», который ничем не хуже «менеджера» или «контроллера» и который наверняка все в разговоре предпочтут «механизму выделения динамической памяти» и «звонок» который является прямым заимствованием из лексикона сидящего за соседним столом коллеги и который мы широко используем в смысле 'kernel call' или 'RPC call'.
НЛО прилетело и опубликовало эту надпись здесь
аллоцированием? ну есть же хорошие русские слова… не?
Это какие? «Выделением»? Или может «распределением»? И название статьи будет «Альтернативные распределяторы памяти» :)
ну… «аллоцированием» я бы наверное заменил на «выделением», а «Альтернативные аллокаторы памяти» или оставил или применил бы «Альтернативные методы/способы/алгоритмы выделения/распределения памяти» в зависимости от ситуации…

и да, выделение и распределение памяти вполне себе благозвучные термины…
Вы наверняка заметили, что слово «аллоцирование» встречается в переводе всего 4 раза, а «выделение» и «размещение» — больше тридцати?
наверняка заметил :) но уж больно это четыре аллоцирования слух режут…
и да, за статью спасибо большое…
Менеджер памяти это называется. Тоже не слишком русское слово, но привычное по крайней мере
НЛО прилетело и опубликовало эту надпись здесь
«выделение памяти» всю жизнь было. Менеджер памяти занимается выделением памяти.
Прочитал до «аж до сюда». Спасибо за пост. Полез гуглить «оценка фрагментации памяти».
Хорошая статья.
Специфические аллокаторы полезны не только для разработчиков игр. Часто очень полезны в счетных алгоритмах с генерацией большого количества данных (типа поиска оптимальных решений). Например, можно просто быстро освободить все данные без деструкторов после вычисления, если они не нужны. Или быстро выделять много данных аллокатором типа пул, если все объекты одинаковые.
по своему опыту могу порекомендовать использовать в пулах не связные списки, которые непонятно зачем там нужны, а маски. В одном int можно сохранить до 32 флагов «занятости» пула. Поиск места под размещения нужного количества блоков прост и удобен.
Также удобны каскадные пулы — когда создается пул с чанками по 4кб-4mb(а все равно кратно надо), часть которых хранит в себе пулы с чанками по Nбайт.

А всем кто на Cях, но все же не в теме — рекомендую просто поставить nedmalloc или мой любимый Winnie::alloc(ну и в этой ветке форума много чего еще написано)
НЛО прилетело и опубликовало эту надпись здесь
Спасибо за наводку (nedmalloc), я даже и не знал, что такое существует — пропатчить аллокатором уже существующие бинарники о_0 (цитата с сайта: nedmalloc can patch itself into existing binaries to replace the system allocator on Windows — for example, Microsoft Word on Windows XP is noticeably quicker for very large documents after the nedmalloc DLL has been injected into it!) Надо будет потестить.
Небольшая шибка перевода:
Часто память, выделяемая в ходе выполнения задачи является временной и сохраняется только на время жизни одного кадра. (В оригинале — lifetime of a single frame)

А вообще статья хорошая. Вот только предложенный «до кучи» двусторонний стек, кажется, ни для чего не нужен.
>> Вот только предложенный «до кучи» двусторонний стек, кажется, ни для чего не нужен.

Очень полезная штука. Часто на геймбое его использовал, для того чтобы совместить аллокации с разным временем жизни. сверху живут временные данные, а снизу добавляются более долгоживущие.
А чем в Вашем случае это было лучше двух стеков?
Под два стека нужно делать два буфера размером N. А тут место пересечения не фиксировано, и можно меньше памяти использовать, например, 1.5N
Ну это только в случае, если суммарный объём памяти мы можем предсказать лучше, чем отдельные слагаемые.
Экономия памяти + большая гибкость =)
В конкретный момент, например, временные данные могут занимать много а долгоживущие — мало. В другое время — наоборот.
Каждый стек — это некий фиксированный блок памяти, который нужно определить и следить чтобы всё влезало. Два стека нужно будет делать большими, что уменьшает смысл в динамическом выделении памяти.

Это ведь ситуация, когда мы наплодили толпу короткоживущих объектов, а потом их постепенно уничтожаем, создавая долгоживущие? Забавное решение, да.
Думаю, да.
Словосочетание «стековый кадр» впервые вижу.
Звучит несколько противоречиво с озвученными в соседних тредиках пожеланиями видеть хорошие русские слова вместо заморских «аллоцирований», не?
Возможно.
Лично мне было бы более понятно «фрейм». И не коробило бы.
Но не факт, что я типичный читатель :)
Реально, чтобы понять, что имелось в виду мне пришлось смотреть на оригинал. И я написал как и подумал — что там ошибка перевода.
Для тех, кто пишет под Windows имеет смысл помнить о стандартных вещах, таких как:
1) Low Fragmentation Heap — только для версий старших, чем Windows 2000 (с каким-то специфичным апдейтом)
2) Small block heap — более старый вариант, по умолчанию отключенный начиная с Windows 2000, в компиляторе из VS2010 вообще выпилен, так что к использованию не рекомендуется.
LFH напомнила схему выделения памяти в memcached.
А вообще…

1. Странно. Разве на SPU приходится гонять код, который память динамически выделяет? Зачем там это?

2. Вроде же приставочные процессоры вполне себе поддерживают виртуальную память, так почему бы не использовать процессы для борьбы с дефрагментацией?

3. malloc не обязательно часто делает syscall'ы. Он вполне способен организовывать пулы из запрошенных у ОС страниц.

4. Где обещанное сравнение с Java?: )
Ничего не буду говорить про 1-3, а 4 никто не обещал. Обещалось что любители делать сравнения могут покормиться найти пищу для размышлений.
И 2) поясните может быть? Каким образом процессы помогут бороться с фрагментацией?
>> Странно. Разве на SPU приходится гонять код, который память динамически выделяет? Зачем там это?
Не все задачи ограничиваются c[i] = a[i]+b[i]
Иногда приходится гулять по движковым структурками, закачивая тоннами всякую мелочевку разного помола. И без стекового аллокатора тут нечего делать.
Данные могут иметь разную структуру — фиксированными массивами не всегда можно отделаться.
Да и просто память в пределах одного джоба может неаднократно переаллоцироваться.

На памяти SPU может одновременно находиться (2-3 job-а) чтобы скрыть латентность обмена с памятью.
Т.е. в пределах фрейма происходят тысячи best-fit аллокаций в любом случае в самой job-системе.

>>Вроде же приставочные процессоры вполне себе поддерживают виртуальную память, так почему бы не использовать процессы для борьбы с дефрагментацией?
Скорее разница в идеологии чем технические проблемы.
Но виртуальная память не избавляет от фрагментации, хотя и смягчает её.
Аллоцируем по N*(1кб + 2кб) блоков до упора (пока _некоммиченая память_ не закончится).
Потом освобождаем все 1-килобайтные. Что дальше? Ни одного блока 3кб уже будет не выделить.

1. А можно конкретнее пример насчёт прогулок по движковым структурам — интересно.

2. Про приставочные процессоры. Я имел в виду виртуальную память вместе с процессами. Если мы для какой-нибудь работы от-fork'али процесс, то он не будет своими служебными malloc/free вносить фрагментацию, скажем так, в корневое адресное пространство. Всё-равно же в приставках SMT-процессоры с выделенными под каждую нить TLB. Почему бы не воспользоваться?
А в приставках так дёшево создаются процессы? И есть какие-то гарантии насчёт того, когда он запустится?
Ну. Ничего не мешает создавать процессы очень дёшево. В Linux, например, они создаются очень быстро, не медленней, чем нити. Гарантии насчёт запуска тоже можно обеспечить — это не сложно. Но вопрос: а зачем? Игрушки неплохо себя чувствуют на стандартных планировщиках Windows/Linux.
1) Движковый это было сказано к слову. Данные могут быть чьи угодно.
Например когда нужно выполнить обход по иерархической структуре, содержащей в своих узлах множество неких обьектов. Весь бардак написан на C++ и каждый обьект содержит всё в себе.
Прыгаем по спискам, где возможно асинхронно, но обычно синхронно — всё равно получается быстро. Где получается медленно — оптимизируем данные для группового доступа.

2) Эээ… тогда я не понял сути вопроса.
Я говорил про то что можно выделить виртуальное адресное пространство без коммита страниц и коммитить их по необходимости. Тогда можно освободившиеся страницы отдавать обратно в систему.

В приставках никаких форков нет и не будет =) Это бесполезный жир.
Процесс (если он вообще есть), владеющий всеми ресурсами консоли — один. Возможны бекграунд процессы обеспечивающие функциональность системы — фоновая закачка, музыка и т.п.
На консолях тонкие RTOS, которые позволяют быть уверенными что ни одного потеряного фрейма не будет. Разве что только по собственной лени и глупости.

>>Игрушки неплохо себя чувствуют на стандартных планировщиках Windows/Linux.
Ценой кучи затраченных ресурсов и отсутствия каких-либо гарантий по производительности и латентности. Работает на самом деле «абы как».

ЭЭэ… Почему бесполезный жир? Оба слова в сочетании не корректны. Во-первых, полезный, потому что упрощает управление ресурсами, используя TLB, как ускоритель для системы управления памятью, помогающим и давление дефрагментации снизить, и мусор собирать очень легко и просто. Во-вторых, не жир: накладные расходы на создание процесса не такие уж и большие.

Откуда у Вас информация про кучу затраченных ресурсов? Я тут недавно писал, так вот, тот же Dead Space 2 в Windows 7 у двухъядерного Athlon II X2 255 отъедает всего по 40 процентов процессорного времени на каждом из ядер. Fallout 2 забирает по 60. Игры, в общем-то, современные и сложные. То есть, там существует большой запас ещё на управление системными всякими вещами… Но и этот запас не нужен, потому что всё и так укладывается в 40-60%.

Кроме того, ну есть же исходники доступные игр (в том числе и таких, как Enemy Territory). И посмотреть на 'борьбу разработчиков с операционной системой' можно посмотреть самостоятельно. Ну нет там никакой такой героической войны, огромных усилий, грязных хаков и всего такого прочего. Всё вполне себе стандартно.
>>Во-первых, полезный, потому что упрощает управление ресурсами

2 процесса не могут упрощать управление ресурсами по сравнению с одним =)

>> используя TLB, как ускоритель для системы управления памятью, помогающим и давление дефрагментации снизить, и мусор собирать очень легко и просто.

Я всё ещё не понимаю как вы хотите бороться с фрагментацией с помощью процессов(!).
TLB эта такая штука, которую лучше на консолях не трогать — это вызов гипервизора + TLB miss очень дорог сам по себе.

>>Игры, в общем-то, современные и сложные.
С чего вы взяли что они должны упираться в CPU?
На консоли можно использовать CPU на 95% и не бояться, что кто-то встрянет на 1 мс и всё сломает.

>> Ну нет там никакой такой героической войны, огромных усилий, грязных хаков и всего такого прочего. Всё вполне себе стандартно
Я имел в виду процессорные ресурсы. При идентичном железе на консоли можно себе позволить гораздо больше. Бич PC — латентности. Везде длинные-длинные буферы чтобы бороться неравномерностью выполнения кода — на случай что кто-то вытеснит игру на значительное время. D3D буфферизирует на несколько кадров вперёд чтобы загрузить GPU.
Из-за этого обратный канал (всякие occlusion query и т.п.) мало полезен.
Звук тоже имеет высокую латентность ~40-50ms. На консоли я могу иметь латентность звука / управления в 16ms и меньше.
С рендером ещё более шоколадно — могу запустить DIP и сразу же получить его данные.
На PS3 можно рендерить на GPU/SPU. Некоторые вещи быстрее делать на SPU, чем на RSX — вертекс процессинг / блюры и т.д. — SPU подключается в нужный момент и выполняет свою часть работы. Всё работает чётко и без задержек. На PC такое в принципе невозможно.

>>А по поводу хождения по структурам на SPU — это сильно странно. Они же для другого предназначены.
Для чего? Это ядра общего назначения. Из-за SIMD ориентированности скалярный код выполняется медленней чем векторизированный, но это не значит что медленно.

>> Разве для проходов по всяким деревьям не предназначены CPU-ядра, которые к этому хорошо приспособлены: автоматические кэши, скалярные операции, всё такое?

SPU много. Если они могут делать работу быстрее чем PPU, зачем нужен PPU?
Можно заготовить данные

продолжаем… (могу постить только раз в час)
Можно заготовить часть данных на PPU, положить их в job (логически завершенный кусок кода, для которого определены входные и выходные данные) и отправить на SPU.
Если job-ов не много, можно не париться. А вот если обход по большой структуре (что уже само тормозит на PPU) и джобы придётся мелко-мелко нарезать (сотни тысяч во фрейм), то лучше и на порядок быстрее это сделать на SPU. Код по большей части останется тем же.
PPU запустит 1 или несколько job-ов, и всё — можно работать дальше.

2 процесса не могут упрощать управление ресурсами по сравнению с одним =)

Я всё ещё не понимаю как вы хотите бороться с фрагментацией с помощью процессов(!).
TLB эта такая штука, которую лучше на консолях не трогать — это вызов гипервизора + TLB miss очень дорог сам по себе.


Эмс… Почему не могут-то? Сценарий очень простой: вот надо нам выполнить некую работу, которая требует выделения динамической памяти. Запускаем её в отдельном процессе, который своей работой не вносит фрагментацию в важную для нас память, в которой мы будем ещё выделять место под важные, долгоживущие в вычислении объекты. Вроде как, чего в этом сложного и не понятного?

TLB miss не так уж и дорог, то есть, конечно, если преднамеренно и регулярно промахиваться, писать код с плохой локальностью, то будет, конечно, дорого. Но если всё написано аккуратно, чем, собственно, промах при работе процесса A будет отличаться от промаха при работе процесса B? Плюс в приставочных процессорах есть возможность разделять TLB между разными процессами: VSID — Virtual Space ID аж целых 37 битов в Cell — вполне достаточно.

SPU много. Если они могут делать работу быстрее чем PPU, зачем нужен PPU?
Можно заготовить данные


Может, как бы, за тем, что SPU хоть и много, но работу их согласовывать надо? А вообще, я вот лично совсем не представляю, как можно эффективно, скажем, поиск в глубину по графу организовать при помощи этих самых SPU. Не все же алгоритмы параллелятся хорошо. А последовательный код SPU не так хорошо выполняет — кэш нужно искусственно поддерживать, накладные расходы на это всё в виде лишних инструкций. Так что… Не понятны мне Ваши заявления.

Про большой кусок насчёт задержек: Но, ведь, люди как-то пишут для PC и вполне качественно выходит. Вот, наприме, а зачем вам управлять звуком точнее, чем 50ms? Даже если m значит тут микро, это всё-равно точность 1/20 секунды, человек этого не воспринимает… И все эти 16ms, или там ещё какие ms… Напоминают погоню некоторых фанатов за скоростью рендеринга в 200fps на мониторах, которые показывают только 60 кадров в секунду.
>> Сценарий очень простой: вот надо нам выполнить некую работу, которая требует выделения динамической памяти. Запускаем её в отдельном процессе, который своей работой не вносит фрагментацию в важную для нас память

Это полный привет с точки зрения производительности. «Работа» которая может выделять память в пределах фрейма, измеряется микросекундами.
Тут сама по себе аллокация памяти тормозит, а вы говорите запустить процесс, переворошить TLB, выделить память, передать данные, обработать данные, передать обратно.

Обьясните мне зачем вообще запускать какой-то процесс? Давайте ещё к формуле 1 цеплять башенный кран.
Гораздо проще работать в виртуальном адресном пространстве.

>>Может, как бы, за тем, что SPU хоть и много, но работу их согласовывать надо? А вообще, я вот лично совсем не представляю, как можно эффективно, скажем, поиск в глубину по графу организовать при помощи этих самых SPU
Тут суперэффективность и не нужна. Нужно чтобы всё вместе уложилось в отведённое время.

Так же как и на любом другом многоядерном процессоре.
Очевидно, имеются свои тараканы с доступом к памяти, но это решается врапперами.
Можно зацепить эмулятор кеша, можно ручками всё делать.

>> А последовательный код SPU не так хорошо выполняет —
С чего бы? В большинстве случаев любой код на SPU быстрее чем PPU.

>> кэш нужно искусственно поддерживать,
накладные расходы на это всё в виде лишних инструкций.

По сравнению с латентностью памяти, несколько инструкций вообще ничего не значат. Читать несколько раз одно и тоже — бессмысленно. Посему от кеша «а-ля CPU» толку мало.
Кешировать нужно не raw-данные, а например стек возврата по дереву и т.п.

>> Вот, наприме, а зачем вам управлять звуком точнее, чем 50ms? Даже если m значит тут микро, это всё-равно точность 1/20 секунды, человек этого не воспринимает

Также как и больше 24 кадров в секунду =)
Игры с войс чатом имеют неприятную задержку при прослушивании своего голоса.
Почитайте про ASIO и кому нужна маленькая латентность.

>>Напоминают погоню некоторых фанатов за скоростью рендеринга в 200fps на мониторах, которые показывают только 60 кадров в секунду.
Причём тут монитор? Всё дело в латентности управления. Например 30fps в Counter-strike это уже за гранью играбельности. К 100 fps там стремятся неспроста.
Это полный привет с точки зрения производительности. «Работа» которая может выделять память в пределах фрейма, измеряется микросекундами.
Тут сама по себе аллокация памяти тормозит, а вы говорите запустить процесс, переворошить TLB, выделить память, передать данные, обработать данные, передать обратно.


Так. Мы же говорим о проблеме фрагментации. Это, во-первых. Во-вторых, да нет там никакого привета с созданием процесса. fork, даже в Linux, где надо ещё заниматься всяким housekeeping'ом для оформления процесса занимает чуть более 2000 тактов (тактов — не микросекунд).

TLB ворошить совершенно не нужно при этом, нужно лишь создать новый VSID, и в нём размещать процесс. В архитектуре Power это всё замечательно предусмотрено. Плюс возможность использовать страницы размером 16MiB. А TLB в тех же Cell'ах держит 1024 вхождения (повторюсь) для разных процессов.

Я не знаю, как там насчёт качества операционной системы, но весь потенциал сделать быстрые процессы есть.

Выделение же памяти выделению — рознь. Если память дефрагментирована, то поиск нужного блока, может занять существенное время. А мы же обсуждаем проблему борьбы с ней.

По сравнению с латентностью памяти, несколько инструкций вообще ничего не значат. Читать несколько раз одно и тоже — бессмысленно. Посему от кеша «а-ля CPU» толку мало. Кешировать нужно не raw-данные, а например стек возврата по дереву и т.п.

Эмс… Странное рассуждение. Когда мы, например, обходим граф, то нам без чтения одного и того же просто не обойтись. Когда мы обходим дерево, то же самое. Наверное, это только самый ярый фанат избегания повторных чтений будет указатели на потомков размещать в разных линиях кэша.

Вообще, важная задача кэша в том виде, в котором он есть на CPU — это ещё и поддержка многозадачности. С программно управляемым кэшем ничего бы не вышло. Но в виде плюшки он даёт возможность, кроме прочего, сберегать объём кода, необходимый для всякого ручного кэширования. А это может быть и не такой уж тривиальный код. Не всегда можно обойтись стэком (алгоритмы на графовых структурах, ray casting, etc).

Причём тут монитор? Всё дело в латентности управления. Например 30fps в Counter-strike это уже за гранью играбельности. К 100 fps там стремятся неспроста

Хм. А как fps связаны с латентностью управления? Вот вы боретесь за все эти такты и микросекунды, а при этом в итоге говорите: ну, впустую нарендерить 40 кадров в секунду — это вполне нормально. Может быть, тут проблема просто в неадекватной структуре движка, у которого латентность управления, почему-то, привязана к fps?
>>Так. Мы же говорим о проблеме фрагментации.
Так вот а причем тут процессы?
Ну запустили вы процесс и что дальше? Что вы там собрались делать?
Мне нужно выделить память чтобы сделать «Hello» + «World».
Вы собираетесь процесс для этого выделять?
Проблему подобных случайных аллокаций решает dlmalloc и делает он это весьма быстро.

Создания второго процесса на консолях может и не быть вообще. Т.к. непонятно как быть с аппаратными ресурсами, некоторые из которые доступны напрямую.

Оригинальная статья рассказывает не об абстрактной фрагментации в вакууме, а об аллокациях в контексте игровых движков, где кроме отсутствия фрагментации нужна ещё и приличная скорость. Опять же на PC с фрагментацией особо не паряться, потому что есть своп — ну лагнёт фрейм, ну и ничего, там все привыкшие.

>> для оформления процесса занимает чуть более 2000 тактов
Т.е. вы хотите сказать, что выделение памяти через CRT будет медленнее чем
если выделить вирт. память в системе, построить новый pagetable создать процесс, запустить его на следующем таймслайсе, сделать тасксвитч, запустить CRT, почистить Bss, АЛЛОЦИРОВАТЬ ПАМЯТЬ ЧЕРЕЗ CRT и т.д.

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

>> Когда мы, например, обходим граф, то нам без чтения одного и того же просто не обойтись.
И? Сделаю полно-ассоциативный кеш, на сколько_нужно кешстрок.

>> Наверное, это только самый ярый фанат избегания повторных чтений будет указатели на потомков размещать в разных линиях кэша.
Если эта структура интрузивна, то распределение поинтеров по кешстрокам будет довольно рыхлым, поэтому держать их в таком виде в кеше — бессмысленная трата памяти.

>>Вообще, важная задача кэша в том виде, в котором он есть на CPU — это ещё и поддержка многозадачности. С программно управляемым кэшем ничего бы не вышло.

А в чём проблема?
Кстати ни в одной игре я пока что ни разу не использовал программный кеш — просто не нужно было. Быстрее и проще загрузить нужные обьекты целиком.

>>Хм. А как fps связаны с латентностью управления?
Очень просто.

Человек нажимает кнопку. Опрос

1. Нет, конечно. Речь не идёт о том, чтобы на каждое hello + world было в отдельном процессе. Ибо тут накладные расходы будут на межпроцессное взаимодействие неприемлемыми. Но если надо, например, построить DAWG по словарю, процесс чего потребует многих аллокаций, перед тем как выдать линейную табличку, то почему нет?

Хотя, наверное, это всё не игровые задачи, а в играх это всё действительно может быть не нужно.

А описанная выше политика вполне себе оправдана, в таких задачах. Потому что выгода от уменьшения дефрагментации может быть выше, чем пара тысячь тактов на создание нового процесса. Чистить же bss тут совершенно не нужно, а создание нового pagetable — это вообще стоимостью два значения в память записать.

2. Очень интересно узнать, а как Вы сделаете ассоциативный кэш эффективно? Со всеми LRU, эвакуацией линий, ранней загрузкой нужного значения и тому подобным. Нет, Вы, конечно, можете сообщить сейчас, что это и не нужно ни разу… Но тратить на каждый доступ в память дополнительно десяток инструкций — не слишком ли это дорого?

3. Проблема с многозадачностью очень простая: а как контекст переключать, если он здоровый и занимает, скажем, 128KiB, потому что без аппаратного кэша, контекстом будет являться вся локальная память. Опять же, Вы можете заявить, что это ни разу не нужно…

4. А что мешает делать опросы в отдельной от графики нити?
>> пара тысячь тактов на создание нового процесса.

Откуда вы это взяли?

>> а создание нового pagetable — это вообще стоимостью два
значения в память записать
2? Как минимум 1024 в page directory и 1024 в как минимум 1 pagetable, а на самом деле гораздо больше.

>> ранней загрузкой нужного значения

Ранней загрузкой откуда? Если адрес ещё не известен?
Если же чтение линейное, то кеш не нужен.

>> Но тратить на каждый доступ в память дополнительно десяток инструкций — не слишком ли это дорого?

Нет. потому что беготня по поинтерам — 100-пудово рано или поздно вызовет чтение из памяти, и десяток инструкций тут не помеха.

>> Проблема с многозадачностью очень простая: а как контекст переключать, если он здоровый и занимает, скажем, 128KiB

Это не так работает как вы думаете. SPU контекст обычно переключается когда заканчивается таймслайс процесса, либо если имеется SPU задача, которая засыпает (например ждёт какого-то события). Сохранение контекста довольно быстрое. ПСП 25GB/s
+ Имеются оптимизации по минимизации обьёма данных — не нужно сохранять весь local store, а только стейт конкретной задачи.
В реальных играх сохранение SPU контекста вообще обычно не происходит.

>> А кто сказал, что возможна только одна истинная организация взаимодействия с игроком и она реализована в CS?

Придумайте лучше =)

>>Почему нельзя разбить рендеринг, физику и взаимодействие с игроком по разным нитям?

Потому что это зависимые операции. Разбитие только увеличит латентность. Опрос контроллеров ничего не занимает, поэтому его нет смысла выносить. Но вы не можете отправлять на рендер сцену, которая ещё не готова.
Если в 1 поточном варианте всё это делается за 1 фрейм, то тут понадобится уже 2.
Добавляем прочие латентности и плачем в подушку.

>>Тем более, что даже на приставках CPU многоядерные, и даже более того, многопоточные

Какая разница? Многоядерность используется на другом уровне — на уровне параллелизма данных и задач.
продолжаем =)
>> А как fps связаны с латентностью управления?
Человек нажимает кнопку. Опрос устройств ввода совершается обычно 1 раз за фрейм.

for each frame {
process_input()
update_scene()
render_scene()
}

Поступившие данные влияют на апдейт игровых объектов. Потом происходит отрисовка. Команды складываются в коммандный буфер GPU,
спустя кадр (с точки зрения CPU) GPU начинает рисовать. На PC, из-за глубокой буферизации уже здесь может быть большая латентность.
Когда кадр отрисован, изображение оказывается на экране на следующем обновлении дисплея. Т.е. если игра работает в 30fps, реальная латентность составляет 83-100мс, а то и больше.

>> Вот вы боретесь за все эти такты и микросекунды, а при этом в итоге

Я борюсь за то, чтобы был стабильный fps на конкретной консоли.
Часто получается, иногда нет. Тут не прокатывает «купи видяху побыстрее».
Микросекунды сами по себе ничего не значат.

>> говорите: ну, впустую нарендерить 40 кадров в секунду — это вполне нормально

Не в пустую =) fps лишним не бывает. В указанном мною CS это определяет уровень играбельности.

Впрочем это уже глубокий оффтоп =)
Нет. А кто сказал, что возможна только одна истинная организация взаимодействия с игроком и она реализована в CS? Почему нельзя разбить рендеринг, физику и взаимодействие с игроком по разным нитям? Тем более, что даже на приставках CPU многоядерные, и даже более того, многопоточные.
А по поводу хождения по структурам на SPU — это сильно странно. Они же для другого предназначены. Разве для проходов по всяким деревьям не предназначены CPU-ядра, которые к этому хорошо приспособлены: автоматические кэши, скалярные операции, всё такое?
спасибо за статью, скорость выросла больше чем в 10 раз!!! но это муторно немного продумывать всю память )) ну иу меня фигня какая-то, с виртуальными методами не работает! точнее при вызове виртуального метода вываливаетм segmentation fault :(
Отличная статья. Кто бы ещё сказал, что она делает на Geektimes вместо центрального хабра?
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории