ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Суббота
20 апреля
848302 Топик полностью
Ксения (15.06.2018 11:20 - 11:33, просмотров: 508) ответил Evgeny_CD на Про техническую основу ->
У меня есть свое ощущение про то, как это работает, по личному опыту. Но оно у меня бездоказательно, т.к. не пыталась доказательства собирать. Если интересно, то ниже излагаю: С проявлением регистров SSE, а следом за ними их расширения AVX, объем арифметических данных, которые пришлось бы запоминать при дезактивации процесса, а затем восстанавливать при его активации, далеко перевалило за килобайт (но еще не достигло размера страницы памяти 4К). И это произошло еще и по той причине, что в отличие от регистров MMX, которые совмещены с регистрами FPU87, регистры SSE/AVX располагаются отдельно, а потому при переключении контекста при переходе обработки одного потока на другой, приходится сохранить в памяти и те регистры, и другие. Более того, грядущие изменения (которые в будущем совершенно неотвратимы) приведут к появлению AVX512, где размер каждого из SIMD-регистров расширится до 64 байт (512 бит), а само количество таких регистров удвоится (станет 32 штуки). Кстати, именно поэтому Intel так косо смотрит на FPU87/MMХ-регистры, планируя совсем изъять их из архитектуры, объявив устаревшей технологией. И это не столько ради экономии памяти при переключении контекстов, сколько ради удаления всего арифметического блока, который их обслуживал (у них свой отдельный арифметический блок), чтобы сократить выделение тепла, которое от SIMD-операций особенно велико, а тем паче, когда тех выполняется параллельно и сразу много. Это уже ныне актуально, т.к. процессоры на техпроцессе 14 нм и выше не справляются с рассеиванием тепла в турбо-режиме, когда SIMD-операциями заняты все ядра (как реальные, так и виртуальные). Говоря о переключении процессов, при котором востребовано сохранение/восстановление контекстов, и я имею в виду не виртуальные ядра, которые тоже называют потоками, а те процессы, которые порождает софт при использовании системы разделения времени, когда после истечения кванта времени происходит принудительный переход к следующему в очереди процессу. Какова величина этого кванта в современных ОС я точно не знаю, но в прошлом этот квант составлял 55 мсек с хвостиком, т.к. это было как раз то время, когда системный таймер выдавал прерывание overflow, чтобы ОС скорректировала время. Вот на этом прерывании, которого избежать было нельзя, обычно и строилась система переключения процессов. Т.е. по этому прерыванию ОС не только корректировала свой счетчик времени, но и переключала текущий процесс на следующий, если его квант времени к этому моменту истек. Соответственно этому, и кванты времени тогда назначались процессам кратными 55 миллисекундам. Очень похоже, что в современных ОС таймерное прерывание вызывается еще чаще - каждую миллисекунду (вероятно связанное с тем, что USB надо с такой же скоростью обслуживать и прочую периферию). О том же косвенно свидетельствуют функции API у Windows, где времена софтверных таймеров для вызова callback-функций задаются в единицах мсек. Выше сказанное мне пришлось проговорить только затем, чтобы очертить проблему, когда система разделения времени, базирующаяся на стратегии переключения процессов/задач, вступает в сильное противоречие с разрастающимся объемом контекста, который при каждом переключении необходимо сперва записать в память, а затем прочесть из ее другого места. Т.е. даже, если гонять 2К в память и столько же обратно не каждую 1 мсек, а только через 55 мсек, то и это будет весьма большими тормозами, даже если та память кэш. Тем не менее, таких сильных тормозов в действительности не ощущается, стало быть, возникает естественное предположение, что арифметический контекст переключается не всякий раз, а "по требованию". Об этом расскажу подробнее. Суть состоит в том, что в регистре статуса новорожденного процесса (но не того, где признаки от последней арифметической операции хранятся) ОС не устанавливает флаг, разрешающий операции с SSE/AVX. Наличие этого флага в статусе имеет исторические корни, когда было необходимо запрещать исполнение этих операций в ОС старого образца, которые еще не умели сохранять контекст SIMD-регистров. Оно и нынче так - например, под WinXP нельзя использовать AVX-арифметику (т.к. она этот флаг выставлять не умеет), даже если сам процессор на это способен. А под Win7SP1 и выше этот флаг уже может быть установлен, и потому AVX-арифметикой пользоваться можно. Так вот фокус состоит именно в том, что ОС намеренно эти флаги (для SSE и AVX) не выставляет новорожденным процессам и арифметический контекст при входе и выходе не сохраняет. Т.е. прямо зырит в статус регистр, и если нет там флага разрешения SSE/AVX, то пропускает перезагрузку соответствующего арифметического контекста (для SSE и AVX он может быть разного объема). В том случае, если новорожденный процесс попытается впервые выполнить запрещенную для него SSE/AVX-операцию, но возникнет прерывание/исключение, на которое ОС прореагирует мягко - абортировать такой процесс не станет, а просто добавит ему этот флаг в статус и велит продолжать его выполнение дальше с того же места. Но теперь уже SSE/AVX-операции будут выполнять у этого процесса быстро, т.к. больше никаких прерываний/исключений от SIMD-операций возникать не будет, однако теперь при переключениях арифметический контекст от такого процесса сохраниться будет, т.к. отношение ОС к нему переменится в связи с наличие флага в статусе. Такой механизм позволяет очень сильно экономить на перезагрузке контекста, благо, что число процессов, использующих SSE/AVX, в общем зачете невелико. Поэтому баг, которому посвящена эта тема, лечится очень просто на уровне ОС - достаточно обнулять арифметический контекст в момент, когда процесс ВПЕРВЫЕ попытался выполнить операцию SSE/AVX. Затраты на это ничтожны, т.к. выполняться это обнуление должно всего лишь однажды за время жизни процесса, а для быстрого его исполнения существует специальная команда vzeroall.