Если я пытаюсь умножить число с плавающей запятой на целое число, быстрее ли умножить его на целое число, представленное целым числом?
int x;
...
float y = 0.5784f * x; //Where x contains a dynamically chosen whole number
или другим поплавком (при условии отсутствия потери точности)
float x;
...
float y = 0.5784f * x; //Where x contains a dynamically chosen and floating point representable whole number
или это сильно различается между аппаратными средствами? Существует ли общая схема (найденная в большинстве устройств с плавающей запятой), которая обрабатывает умножение с плавающей запятой и целое число, или является общей практикой для оборудования сначала преобразовывать целое число в число с плавающей запятой, а затем использовать схему, которая выполняет float * float? Что, если представляемое целое число чрезвычайно мало, например, значение 0 или 1 определяется динамически и используется для определения того, добавляется ли число с плавающей запятой к сумме без ветвления?
int x;
...
float y = 0.5784f + 0.3412f * x; //Where x contains either 0 or 1 (determined dynamically).
Спасибо за помощь в продвижении.
@MartinYork Очень интересно и полезно знать. Вы случайно не знаете, где я могу такие спецификации, как о языке. Не прошу вас тратить время на просеивание, чтобы найти именно эту строку, просто общее место, где существуют подобные языковые спецификации.
Вы можете найти ссылки на стандарт здесь: stackoverflow.com/a/4653479/14065 «ПРАВИЛО КАК ЕСЛИ» Раздел 4.1 [intro.abstract] Соответствующие реализации необходимы для эмуляции (только) наблюдаемого поведения абстрактной машины как поясняется ниже. «АРИФМЕТИЧЕСКИЕ ПРЕОБРАЗОВАНИЯ» Раздел 7.4 [expr.arith.conv] Параграф 1 Пункт 4: В противном случае, если один из операндов имеет число с плавающей точкой, другой должен быть преобразован в число с плавающей запятой.
В основном стандарт описывает, как он хочет, чтобы язык вел себя. Он никоим образом не ограничивает реализацию, пока наблюдаемое поведение соответствует стандарту. Это позволяет проводить высокоэффективную оптимизацию, если компилятор может доказать себе, что наблюдаемое поведение не изменилось в результате оптимизации.
@MartinYork Спасибо за ссылку, я буду рассказывать об этом в следующий раз, когда застряну, возможно, у меня будет шанс ответить на многие из моих собственных вопросов!
Быстрее ли умножать число с плавающей запятой на целое число или другое число с плавающей запятой?
В общем, float * float
быстрее, но я подозреваю, что разницы почти нет. Скорость программы зависит от всего кода, а не только от этой строки. Быстрее здесь может стоить на один больше в других местах.
Доверьтесь своему компилятору или найдите лучший компилятор для создания кода, который 0.5784f * some_int
работает хорошо.
В случае 0.5784f * some_int
язык обязывает some_int
действовать так, как будто он сначала преобразуется в float
*1 перед умножением. Но сообразительный компилятор может знать о конкретных приемах реализации, чтобы выполнять умножение лучше/быстрее напрямую без отдельного явного преобразования - до тех пор, пока он получает допустимый результат.
В float y = 0.5784f + 0.3412f * x; //Where x contains either 0 or 1 (determined dynamically).
компилятор тоже может увидеть это и воспользоваться преимуществом для создания эффективного кода.
Только в избранных случаях и с опытом вы сможете перехитрить компилятор. Код для ясности сначала.
Вы всегда можете профилировать разные коды/параметры компилятора и сравнивать.
Совет: по моему опыту, я нахожу больший прирост производительности при большем просмотре кода, чем при опубликованной проблеме, что граничит с микрооптимизацией.
*1 См. FLT_EVAL_METHOD
другие возможности.
Также полезно сообщить, что они могут скомпилировать с различными уровнями оптимизации, выгружая сборку и просто проверяя :)
Спасибо за ответ, и за продолжение. Да, я знаю, что вам не следует пытаться превзойти компилятор, и я на самом деле не пытаюсь, это больше касается моего теоретического понимания, чем практического, и увеличения моей способности рассуждать с помощью оптимизированной компилятором сборки (почему принимаются определенные решения), вот почему я еще раз благодарю вас за то, что вы включили то, что обязывает язык. Я также мог бы добавить ссылку на то, где существуют такие правила для языка (не обязательно это правило в частности), это было бы очень признательно и, вероятно, решило бы многие другие вопросы, которые у меня в конечном итоге возникнут.
@Ryoku «добавить ссылку на то, где существуют такие правила для языка» на самом деле все в спецификации C.. Для *
см. § 6.5.5 1 «Обычные арифметические преобразования выполняются над операндами».
@chux-ReinstateMonica большое спасибо за ссылку, я не совсем понял, что искать
Язык требует, чтобы целое число было преобразовано в число с плавающей запятой перед умножением. Хотя в языке также есть правило "как если бы": если он может сделать это лучше по-другому (и получить тот же результат), то ему разрешено это делать.