На некоторых процессорах умножение с плавающей запятой происходит так же быстро, как сложение, потому что:
- Разработчики аппаратного обеспечения установили множество логических элементов в модулях с плавающей запятой.
- Инструкции могут быть разделены на несколько этапов, которые выполняются в конвейере. Например, умножение может выполнять часть своей работы в блоке M0, а затем передавать результаты в блок M1, который выполняет другую часть, затем M2, затем M3. Пока M1 работает со своей стороны, M0 может начать работу с другим умножением. При таком расположении умножение может фактически занять четыре такта процессора для завершения, но, поскольку четыре блока работают на четырех этапах, процессор может завершать одно умножение каждый цикл. Напротив, более простая инструкция, такая как XOR, имеет только одну стадию.
- Хотя некоторые инструкции могут быть выполнены быстро, а некоторые требуют большего времени, весь процессор синхронизируется с помощью часов, и каждый этап конвейера в каждом исполнительном блоке имеетзавершить свою работу в один такт. Это налагает некоторую жесткость на дизайн процессора - некоторые простые операции завершат свою работу до окончания тактового цикла, в то время как сложные операции требуют полного цикла. Дизайнеры принимают решение о том, как долго делать тактовый цикл. Если тактовый цикл слишком короткий (относительно скорости, с которой работают логические элементы), тогда для многих команд требуется несколько циклов и могут потребоваться дополнительные издержки для их управления. Если тактовый цикл слишком длинный, то время тратится впустую, ожидая инструкций, которые могли бы завершиться раньше. В современной процессорной технологии распространено, что ступени умножителя с плавающей запятой хорошо работают с временем цикла процессора.
Тем не менее, вы можете увидеть разницу между временем сложения и умножения. Современные конструкции процессоров довольно сложны, и процессоры обычно имеют несколько блоков для выполнения различных операций с плавающей запятой. Процессор может иметь больше единиц для выполнения сложения, чем для умножения, поэтому он может делать больше операций за единицу времени, чем умножения.
Однако, соблюдайте выражение, которое вы используете:
sum += q[i] + q[i - 1];
Это приводит к последовательной зависимости sum
от его предыдущего значения. Процессор может добавить q[i]
к q[i-1]
, не дожидаясь предшествующего добавления, но затем, чтобы добавить к sum
, он должен дождаться завершения предыдущего добавления к sum
. Это означает, что, если процессор имеет два дополнительных блока, он может одновременно работать как с q[i] + q[i-1]
, так и с предыдущим добавлением к sum
. Но, если бы у него было больше дополнительных единиц, он не мог бы двигаться быстрее. Он может использовать дополнительные единицы, чтобы сделать больше этих q[i] + q[i - 1]
дополнений для различных значений i
, но каждое добавление к sum
должно ждать предыдущего. Следовательно, с двумя или более единицами сложения это вычисление зависит от задержки сложения, то есть того, сколько времени требуется для одного сложения. (Это в отличие от пропускной способности сложения, то есть того, сколько сложений процессор может сделать за единицу времени, если нет последовательной зависимости.)
Если вы использовали другойвычислений, таких как sum += q[i];
или sum0 += q[i]; sum1 += q[i+1]; sum2 += q[i+2]; sum3 += q[i+3];
, тогда вы могли видеть различное время сложения и умножения, которое зависело от того, сколько единиц сложения и сколько умножителей было у процессора.