2013-05-22 3 views
5

Как известно, процессор X86 имеет 64-битную шину данных. Я понимаю, что ЦП не может получить доступ к произвольному адресу. Адрес, к которому может обращаться ЦП, является целочисленным кратным ширине его шины данных. Для производительности переменные должны начинаться с (в соответствии с) этими адресами, чтобы избежать дополнительного доступа к памяти. 32-битные переменные, привязанные к 4Byte-границам, будут автоматически выровнены с 8-битной (64-битной) границей, что соответствует 64-битной шине данных x86. Но почему компиляторы выровняют 128-битные переменные с 16-битной границей? Не 8-байтовая граница?Почему 128-битные переменные должны быть выровнены с границей 16Byte

Thanks

Позвольте мне уточнить детали. Компиляторы используют длину переменной для ее выравнивания. Например, если переменная имеет длину в 256 бит, Complier выровняет ее с 32-битной границей. Я не думаю, что какой-то процессор имеет такую ​​длинную шину данных. Кроме того, обычные памяти DDR передают только 64-битные данные один раз, несмотря на кеш, как память может заполнить более широкую шину данных процессора? или только с помощью кеша?

+3

«Как известно, процессор X86 имеет 64-битную шину данных» - это неверно. x86 ничего не говорит о размерах шины данных. Современные процессоры на самом деле имеют большую ширину шины данных, чем это. – Mysticial

+4

Процессор не считывает данные с шины данных, они читают его из кеша. Для избежания трансграничения границы строки кэша требуется выравнивание по 16 байт. –

+0

@Mysticial Я думаю, что самые популярные процессоры x86 в настоящее время имеют 64-битную шину данных, не так ли? – iqapple

ответ

4

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

Рассмотрим массив из 16-байтных объектов, который начинается с адреса, который состоит из восьми байтов, но не из 16 байтов. Предположим, что процессор имеет восьмибайтную шину, как указано в вопросе, даже если некоторые процессоры этого не делают. Однако обратите внимание, что в какой-то момент в массиве один из объектов должен оседлать границу страницы: Карта памяти обычно работает на 4096-байтных страницах, которые начинаются с 4096-байтных границ. С восьмибайтовым выровненным массивом некоторый элемент массива будет начинаться с байта 4088 на одной странице и продолжить до байта 7 следующей страницы.

Когда программа пытается загрузить 16-байтовый объект, который пересекает границу страницы, он больше не может выполнять одну карту виртуальной-физической памяти. Он должен сделать один поиск для первых восьми байтов и другой поиск для вторых восьми байтов. Если блок загрузки/хранения не предназначен для этого, тогда инструкция требует специальной обработки. Процессор может прервать свою первоначальную попытку выполнить инструкцию, разделить ее на два специальных микроинструкции и отправить их обратно в очередь команд для выполнения. Это может задержать инструкцию по многим циклам процессора.

Кроме того, как отметил Ханс Пассант, выравнивание взаимодействует с кешем. Каждый процессор имеет кэш памяти, и общий кэш обычно организован в 32-байтовые или 64-байтовые «строки». Если вы загружаете 16-байтовый объект с выравниванием по 16 байт, а объект находится в кеше, то кеш может предоставить одну строку кеша, которая содержит необходимые данные. Если вы загружаете 16-байтные объекты из массива, который не выравнивается по 16 байт, тогда некоторые из объектов в массиве будут разделять две строки кэша. Когда эти объекты загружаются, из кэша должны быть извлечены две строки. Это может занять больше времени. Даже если для получения двух строк потребуется больше времени, возможно, потому, что процессор предназначен для обеспечения двух строк кэша за цикл, это может помешать другим вещам, которые выполняет программа. Обычно программа загружает данные из нескольких мест. Если нагрузки эффективны, процессор может выполнять два одновременно. Но если для одного из них требуется две строки кэша вместо обычной, он блокирует одновременное выполнение других операций загрузки.

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

+0

Я знаю, что вы правы, даже если некоторые моменты являются эзотерическими для меня. – iqapple

+0

ИМО, большинство из этого ответа, будучи само по себе истинным, не имеет значения для qustion, который был «Но почему компиляторы вывести 128-битные переменные в 16-битную границу? ». Ответ на этот вопрос заключается в простоте того, что аппаратное обеспечение требует этого, компилятор не делает этого не потому, что он более эффективен, а потому, что любой другой способ не будет работать. вы говорите: «Рассмотрим массив из 16-байтных объектов, который начинается с адреса, который состоит из восьми байтов, но не из 16 байт». Ну, это просто не сработает (потому что аппаратное обеспечение процессора не поддерживает его) независимоиз того, пересекает ли массив границу страницы. – Bull

+0

На самом деле это зависит от того, что вопрос подразумевал под «переменной». Я думал о 128 переменных, таких как __m128i. Если это касается таких вещей, как 'struct foo {char x [128];};" то я согласен с Эриком. – Bull

5

Одна из причин заключается в том, что большинство инструкций SSE2 на X86 требуют, чтобы данные были выровнены по 128 бит. Это конструктивное решение было бы принято по соображениям производительности и избежать чрезмерно сложного (и, следовательно, медленного и большого) оборудования.

+0

Я думаю, что это, вероятно, правильно. Я застрял здесь в цикле, пытаясь выяснить, какие компиляторы автоматически выравнивают __m128i тип, который используется для векторизованного вычисления SIMD. –