Оптимизация: быстрее ли умножать число с плавающей запятой на целое число или другое число с плавающей запятой

Если я пытаюсь умножить число с плавающей запятой на целое число, быстрее ли умножить его на целое число, представленное целым числом?

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).

Спасибо за помощь в продвижении.

Язык требует, чтобы целое число было преобразовано в число с плавающей запятой перед умножением. Хотя в языке также есть правило "как если бы": если он может сделать это лучше по-другому (и получить тот же результат), то ему разрешено это делать.

Martin York 21.12.2020 07:05

@MartinYork Очень интересно и полезно знать. Вы случайно не знаете, где я могу такие спецификации, как о языке. Не прошу вас тратить время на просеивание, чтобы найти именно эту строку, просто общее место, где существуют подобные языковые спецификации.

Ryoku 21.12.2020 07:26

Вы можете найти ссылки на стандарт здесь: stackoverflow.com/a/4653479/14065 «ПРАВИЛО КАК ЕСЛИ» Раздел 4.1 [intro.abstract] Соответствующие реализации необходимы для эмуляции (только) наблюдаемого поведения абстрактной машины как поясняется ниже. «АРИФМЕТИЧЕСКИЕ ПРЕОБРАЗОВАНИЯ» Раздел 7.4 [expr.arith.conv] Параграф 1 Пункт 4: В противном случае, если один из операндов имеет число с плавающей точкой, другой должен быть преобразован в число с плавающей запятой.

Martin York 21.12.2020 19:50

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

Martin York 21.12.2020 19:55

@MartinYork Спасибо за ссылку, я буду рассказывать об этом в следующий раз, когда застряну, возможно, у меня будет шанс ответить на многие из моих собственных вопросов!

Ryoku 22.12.2020 00:55
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
5
1 104
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Быстрее ли умножать число с плавающей запятой на целое число или другое число с плавающей запятой?

В общем, 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 другие возможности.

Также полезно сообщить, что они могут скомпилировать с различными уровнями оптимизации, выгружая сборку и просто проверяя :)

David C. Rankin 21.12.2020 07:08

Спасибо за ответ, и за продолжение. Да, я знаю, что вам не следует пытаться превзойти компилятор, и я на самом деле не пытаюсь, это больше касается моего теоретического понимания, чем практического, и увеличения моей способности рассуждать с помощью оптимизированной компилятором сборки (почему принимаются определенные решения), вот почему я еще раз благодарю вас за то, что вы включили то, что обязывает язык. Я также мог бы добавить ссылку на то, где существуют такие правила для языка (не обязательно это правило в частности), это было бы очень признательно и, вероятно, решило бы многие другие вопросы, которые у меня в конечном итоге возникнут.

Ryoku 21.12.2020 07:49

@Ryoku «добавить ссылку на то, где существуют такие правила для языка» на самом деле все в спецификации C.. Для * см. § 6.5.5 1 «Обычные арифметические преобразования выполняются над операндами».

chux - Reinstate Monica 21.12.2020 10:05

@chux-ReinstateMonica большое спасибо за ссылку, я не совсем понял, что искать

Ryoku 21.12.2020 10:16

Другие вопросы по теме