Я провел несколько тестов времени, а также прочитал несколько статей, подобных этой (последний комментарий), и похоже, что в сборке Release значения float и double занимают одинаковое время обработки.
Как это возможно? Когда float менее точен и меньше по сравнению с двойными значениями, как CLR может удвоить время обработки?
c#
.net
clr
performance
Джоан Венге
источник
источник
Ответы:
На x86 процессорах, по крайней мере,
float
иdouble
каждый из них будет преобразованы в 10-байтовой реальный по FPU для обработки. FPU не имеет отдельных блоков обработки для различных типов с плавающей запятой, которые он поддерживает.Старинный совет, который
float
действует быстрее, чемdouble
применявшийся 100 лет назад, когда большинство процессоров не имели встроенных FPU (и немногие люди имели отдельные чипы FPU), поэтому большинство операций с плавающей запятой производилось программно. На этих машинах (которые приводились в движение паром, вырабатываемым лавовыми ямами) было быстрее использоватьfloat
s. Единственное реальное преимуществоfloat
s заключается в том, что они занимают меньше места (что имеет значение только в том случае, если у вас их миллионы).источник
Это зависит от 32-битной или 64-битной системы. Если вы компилируете в 64-битную версию, удвоение будет быстрее. Скомпилировано в 32-битную версию на 64-битной (машина и ОС), что примерно на 30% быстрее:
public static void doubleTest(int loop) { Console.Write("double: "); for (int i = 0; i < loop; i++) { double a = 1000, b = 45, c = 12000, d = 2, e = 7, f = 1024; a = Math.Sin(a); b = Math.Asin(b); c = Math.Sqrt(c); d = d + d - d + d; e = e * e + e * e; f = f / f / f / f / f; } } public static void floatTest(int loop) { Console.Write("float: "); for (int i = 0; i < loop; i++) { float a = 1000, b = 45, c = 12000, d = 2, e = 7, f = 1024; a = (float) Math.Sin(a); b = (float) Math.Asin(b); c = (float) Math.Sqrt(c); d = d + d - d + d; e = e * e + e * e; f = f / f / f / f / f; } } static void Main(string[] args) { DateTime time = DateTime.Now; doubleTest(5 * 1000000); Console.WriteLine("milliseconds: " + (DateTime.Now - time).TotalMilliseconds); time = DateTime.Now; floatTest(5 * 1000000); Console.WriteLine("milliseconds: " + (DateTime.Now - time).TotalMilliseconds); Thread.Sleep(5000); }
источник
Math
работает с double. Но вы неправильно прочитали мой пост: мои тесты показали, что у меня лучше плавать по производительности.float
иdouble
производительность практически идентичны. Разница менее 0,3% при усреднении по множеству независимых испытаний, где в каждом испытании выполнялись операции умножения, деления и сложения последовательно связанных переменных (во избежание любых оптимизаций компилятора). Я попробовал второй набор тестов сMath.Sin()
иMath.Sqrt()
а также получили одинаковые результаты.У меня был небольшой проект, в котором я использовал CUDA, и я помню, что float там тоже был быстрее, чем double. На этот раз трафик между хостом и устройством ниже (хост - это ЦП, а «нормальная» ОЗУ, а устройство - это графический процессор и соответствующая ОЗУ). Но даже если данные постоянно находятся на устройстве, это медленнее. Думаю, я где-то читал, что это изменилось недавно или должно измениться в следующем поколении, но я не уверен.
Таким образом, кажется, что графический процессор просто не может изначально обрабатывать двойную точность в этих случаях, что также объясняет, почему обычно используется GLFloat, а не GLDouble.
(Как я уже сказал, это насколько я помню, я просто наткнулся на это, когда искал float vs. double на CPU.)
источник
Тем не менее, в некоторых случаях предпочтительнее использовать числа с плавающей запятой - например, при кодировании OpenGL гораздо чаще используется тип данных GLFloat (обычно отображаемый напрямую в 16-битное число с плавающей запятой), поскольку он более эффективен на большинстве графических процессоров, чем GLDouble.
источник