Является ли удвоение быстрее, чем плавает на С#?

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

Ответ 1

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

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

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

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

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

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

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

Ответ 2

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

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

Ответ 3

Я только что прочитал "Фонд разработки приложений Microsoft.NET Framework 2" для экзамена MCTS 70-536 и есть примечание на стр. 4 (глава 1):

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

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

Ответ 4

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

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

Ответ 5

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

Что с Core i7 920

Ответ 6

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

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

Ответ 7

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

Ответ 8

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

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

Ответ 9

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

Ответ 10

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

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

Это на моем i7 920, работающем на 64-разрядной операционной системе.