Удваивается ли быстрее, чем с плавающей точкой в ​​C #? - PullRequest
53 голосов
/ 01 октября 2008

Я пишу приложение, которое читает большие массивы с плавающей точкой и выполняет с ними несколько простых операций. Я использую поплавки, потому что я думал, что это будет быстрее, чем удваивается, но после некоторых исследований я обнаружил, что есть некоторая путаница в этой теме. Кто-нибудь может уточнить это?

Ответы [ 10 ]

63 голосов
/ 01 октября 2008

Короткий ответ: «используйте ту точность, которая требуется для приемлемых результатов».

Ваша единственная гарантия заключается в том, что операции, выполняемые с данными с плавающей запятой, выполняются как минимум в элементе выражения с наивысшей точностью. Таким образом, умножение двух float выполняется по крайней мере с точностью float , и умножение float и double будет выполнено по крайней мере с двойной точностью. Стандарт гласит, что «операции [с плавающей запятой] могут выполняться с более высокой точностью, чем тип результата операции».

Учитывая, что JIT для .NET пытается оставить ваши операции с плавающей запятой с запрошенной точностью, мы можем взглянуть на документацию Intel для ускорения наших операций. На платформе Intel ваши операции с плавающей запятой могут выполняться с промежуточной точностью 80 бит и конвертироваться до требуемой точности.

Из руководства Intel по операциям C ++ с плавающей запятой 1 (извините, только мертвое дерево), они упоминают:

  • Используйте тип с одинарной точностью (например, float), если не требуется дополнительная точность, полученная с помощью double или long double. Более точные типы увеличивают требования к объему памяти и пропускной способности. ...
  • Избегайте арифметических выражений смешанного типа данных

Этот последний пункт важен, так как вы можете замедлить себя с помощью ненужных приведений к / с float и удвоить , что приводит к JIT-коду, который запрашивает x87 отбрасывать его 80-битный промежуточный формат между операциями!

1. Да, это говорит C ++, но стандарт C # плюс знание CLR позволяет нам знать, что информация для C ++ должна быть применима в этом случае.

20 голосов
/ 05 декабря 2010

Я только что прочитал «Microsoft .NET Framework-Application Development Foundation 2-й» для экзамена MCTS 70-536, и на странице 4 (глава 1) есть примечание:

ПРИМЕЧАНИЕ Оптимизация производительности с помощью встроенных типов
Среда выполнения оптимизирует производительность 32-разрядных целочисленных типов (Int32 и UInt32), поэтому используйте эти типы для счетчиков и других часто используемых интегральных переменных. Для операций с плавающей точкой Double является наиболее эффективным типом, поскольку эти операции оптимизируются аппаратно.

Это написано Тони Нортрупом. Я не знаю, является ли он авторитетом или нет, но я ожидаю, что официальная книга для экзамена .NET должна иметь определенный вес. Это конечно не гарантия. Я просто думал, что добавлю это в это обсуждение.

19 голосов
/ 02 октября 2008

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

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

7 голосов
/ 26 июня 2009

Я пишу трассировщик лучей, и замена поплавков на двойные для моего класса Color дает мне 5% ускорение. Замена векторов с плавающей запятой еще на 5% быстрее! Довольно круто :) 1001 *

Это с Core i7 920

7 голосов
/ 02 октября 2008

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

Кто-то еще упомянул, что нужно избегать преобразований между float и double и вычислений, использующих операнды обоих типов. Это хороший совет, и если вы используете какие-либо функции математической библиотеки, которые возвращают удвоенные значения (например), то сохранение всего как двойных будет быстрее.

4 голосов
/ 02 октября 2008

С арифметикой 387 FPU, float только быстрее, чем double, для некоторых длинных итерационных операций, таких как pow, log и т. Д. (И только если компилятор устанавливает управляющее слово FPU соответствующим образом).

С упакованной арифметикой SSE, однако, это имеет большое значение.

3 голосов
/ 06 января 2011

Matthijs

Вы не правы. 32-битная версия гораздо эффективнее 16-битной - в современных процессорах ... Возможно, не в отношении памяти, но по эффективности 32-битная - это путь.

Вы действительно должны обновить своего профессора до чего-то более "современного". ;)

Во всяком случае, чтобы ответить на вопрос; float и double имеют точно такую ​​же производительность, по крайней мере, на моем Intel i7 870 (как в теории).

Вот мои измерения:

(Я создал «алгоритм», который повторил 10 000 000 раз, а затем повторил его 300 раз, и из этого я получил среднее значение).

double
-----------------------------
1 core  = 990 ms
4 cores = 340 ms
6 cores = 282 ms
8 cores = 250 ms

float
-----------------------------
1 core  = 992 ms
4 cores = 340 ms
6 cores = 282 ms
8 cores = 250 ms
1 голос
/ 11 сентября 2010

Я всегда думал, что процессоры были оптимизированы или одинаковы независимо от числа операций с плавающей запятой или удвоения. В поисках оптимизаций для моих интенсивных вычислений (много получений из матрицы, сравнения двух значений) я обнаружил, что числа с плавающей запятой работают примерно на 13% быстрее.

Это удивило меня, но я думаю, это связано с характером моей проблемы. Я не делаю приведения между float и double в ядре операций, и мои вычисления в основном складываются, умножаются и вычитаются.

Это на моем i7 920 с 64-битной операционной системой.

1 голос
/ 01 октября 2008

Плавание должно быть быстрее в 32-битной системе, но профилируйте код, чтобы убедиться, что вы оптимизируете правильную вещь.

1 голос
/ 01 октября 2008

Это означает, что числа с плавающей запятой немного быстрее, чем удваиваются: http://www.herongyang.com/cs_b/performance.html

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

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