Float vs Double Performance
-
03-07-2019 - |
Вопрос
Я провел несколько временных тестов, а также прочитал несколько статей, таких как этот (последний комментарий), и похоже, что в выпусках сборки, значения типа float и double занимают одинаковое количество времени обработки.
Как это возможно? Когда float менее точен и меньше по сравнению с двойными значениями, как CLR может получить удвоения за одно и то же время обработки?
Решение
На процессорах x86, по крайней мере, float
и double
будут преобразованы FPU для обработки в 10-байтовое вещественное число. FPU не имеет отдельных блоков обработки для различных типов с плавающей точкой, которые он поддерживает.
Старый совет, что float
быстрее, чем double
, который применялся 100 лет назад, когда большинство процессоров не имели встроенных FPU (и мало кто имел отдельный FPU микросхемы), поэтому большинство операций с плавающей точкой было сделано в программном обеспечении. На этих машинах (которые питались паром, генерируемым лавовыми ямами), был быстрее, чтобы использовать float
. Теперь единственное реальное преимущество для float
заключается в том, что они занимают меньше места (что имеет значение, только если их у вас миллионы).
Другие советы
У меня был небольшой проект, в котором я использовал CUDA, и я помню, что float там тоже был быстрее, чем double. Как только трафик между Хостом и Устройством становится меньше (Хост - это ЦП, а «нормальная» ОЗУ и Устройство - это ГП и соответствующая ОЗУ). Но даже если данные постоянно находятся на устройстве, это медленнее. Мне кажется, я где-то читал, что это недавно изменилось или должно измениться со следующим поколением, но я не уверен.
Похоже, что GPU просто не может обрабатывать двойную точность изначально в этих случаях, что также объясняет, почему обычно используется GLFloat, а не GLDouble.
(Как я уже сказал, это только насколько я помню, просто наткнулся на это во время поиска float против double на процессоре.)
Это зависит от 32-битной или 64-битной системы. Если вы компилируете в 64-битную версию, double будет быстрее. Скомпилированный в 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);
}
Тем не менее, в некоторых случаях предпочтение отдается плавающим числам - например, в кодировке OpenGL гораздо более распространенным является использование типа данных GLFloat (обычно сопоставляемого непосредственно с 16-битным плавающим числом), поскольку он более эффективен на большинстве графических процессоров, чем GLDouble. р>