P6 Архитектура - За исключением переименования регистров, ограниченные пользовательские регистры приводят к большему количеству операций, потраченных на разлив / загрузку? - PullRequest
6 голосов
/ 17 марта 2010

Я изучаю дизайн JIT с точки зрения реализации виртуальных языков на динамических языках. Я не делал много сборок с 8086/8088 дней, просто немного здесь или там, так что будьте добры, если я не в духе.

Насколько я понимаю, архитектура x86 (IA-32) по-прежнему имеет тот же базовый набор ограниченных регистров, что и всегда, но количество внутренних регистров значительно возросло, но эти внутренние регистры, как правило, недоступны и используются с переименованием регистров для достижения параллельной конвейеризации кода, который в противном случае не мог бы быть распараллеливаемым. Я понимаю эту оптимизацию довольно хорошо, но мне кажется, что, хотя эти оптимизации помогают в общей пропускной способности и для параллельных алгоритмов, ограниченный набор регистров, который мы все еще застряли, приводит к увеличению издержек при проливе регистров, так что если x86 имел двойной или четырехкратный регистры доступно нам, может быть значительно меньше push / pop кодов операций в типичном потоке команд? Или есть другие варианты процессора, которые также оптимизируют это, о чем я не знаю? В основном, если у меня есть блок кода, который имеет 4 регистра для работы с целыми числами, но у моего блока есть дюжина переменных, у меня есть потенциально push / pop для каждых 2 или около того инструкций.

Есть ли ссылки на учебу или, что еще лучше, на личный опыт?

РЕДАКТИРОВАТЬ: x86_64 имеет 16 регистров, что является двойным x86-32, спасибо за исправление и информацию.

Ответы [ 2 ]

10 голосов
/ 17 марта 2010

В дополнение к переименованию регистров, чтобы скрыть пузырьки из-за задержек инструкций, большинство архитектур x86 достаточно умны, чтобы подсчитывать нажатия и всплески и переименовывать их в регистры. Помните, что декодер команд на x86 фактически выполняет своего рода JIT-компиляцию, превращая поток команд x86 в небольшую программу микрокода, хранящуюся в кэше трассировки. Часть этого процесса включает перехват загрузок стека с небольшим смещением и преобразование их в регистры. Таким образом что-то вроде (явно глупо и чисто, например):

lwz eax,[ebp]
lwz ebx,[ebp+4]
add eax,[edx+0]
push eax 
lwz eax,[ebp+8]
add eax,ebx
pop ebx
add eax,ebx

готовит что-то вроде (представьте, что внутренние регистры называются например, r0..r16):

lw r3, edx
lw r1, ebp
lw r2, ebp+4 ; the constant '4' is usually stored as an immediate operand
add r1,r2
or r4,r1,r1 ;; move r1 to r4
lw r1, ebp+8
add r1,r2
or r2,r4,r4
add r1,r2

Конечно, магически умный декодер (в отличие от того, который фактически вписывается в счетчик транзисторов) может разрушить некоторые ненужные движения, но я хочу сказать, что push / pop и сохраняет / загружает в esp+(some small number) на самом деле превратился в теневые регистры.

4 голосов
/ 17 марта 2010

Два очка:

(1) x86-64 удваивает количество регистров до 16

(2) в современных процессорах x86, инструкция, использующая область памяти, которая уже находится в кэше L1, почти так же быстро, как и та же операция с операндом регистра, так что вы можете почти думать о L1 как «регистр памяти»

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...