Проблема
У нас есть несколько машин с Ubuntu с очень похожими характеристиками.Мы запустили простую программу для проверки проблемы, которую мы видим в виртуальной машине Windows, на которой работает каждая из этих машин.Скомпилировано с использованием gcc 4.8.4 на 64-битной машине Linux и v140 в Visual Studio на 64-битной виртуальной машине Windows.
#include <cmath>
#include <stdio.h>
int main()
{
double num = 1.56497856262158219209;
double numHalf = num / 2.0;
double cosVal = cos(num);
double cosValHalf = cos(numHalf);
printf("num = %a\n", num);
printf("numHalf = %af\n", numHalf);
printf("cosVal(num) = %a\n", cosVal);
printf("cosValHalf(numHalf) = %a\n", cosValHalf);
//system("pause");
return 0;
}
Проблема возникает при запуске одного и того же двоичного файла на хост-машинах с определенными ЦП..
Результаты
В Linux все машины выдают одинаковый результат.На виртуальной машине Windows выдаются разные результаты, даже если версии и настройки виртуальной машины одинаковы.Кроме того, двоичные файлы, генерируемые на каждой виртуальной машине, будут давать разные результаты при перемещении на другой хост-компьютер;т.е. двоичный файл, сгенерированный в VM2, но выполненный на LM1, возвратил те же результаты, как если бы VM1 сгенерировал двоичный файл.Мы даже скопировали виртуальную машину, чтобы подтвердить это поведение и, конечно же, оно продолжается.
С усилиями, описанными выше, я думаю, что это не различие библиотеки или проблема виртуальной машины.Что касается выходных данных, следующие процессоры выдают эти результаты:
- Процессор Intel® Xeon® E5-2630 0
- Процессор Intel® Xeon® E5-2630 v2
Прежние процессоры дают одинаковые результаты для Linux и Windows.Результаты представлены в шестнадцатеричном виде, потому что читаемость имеет значение меньше, чем при наличии расхождений.
num = 0x1.90a26f616699cp+0
numHalf = 0x1.90a26f616699cp-1
cosVal(num) = 0x1.7d4555e817bdcp-8
cosValHalf(numHalf) = 0x1.6b171bb5e3434p-1
Эти процессоры дают результаты на виртуальной машине Windows, отличные от их аналога Linux:
- Intel® Xeon (R) CPU E5-2630 v3
- Intel® Xeon (R) CPU E3-1270 v5
Я не уверен, как эти результаты достигаются.Разборка на VS2015 показывает, что обе программы генерируют одинаковые инструкции независимо от того, на каком хост-компьютере он был скомпилирован.
num = 0x1.90a26f616699cp+0
numHalf = 0x1.90a26f616699cp-1
cosVal(num) = 0x1.7d4555e817bdcp-8
cosValHalf(numHalf) = 0x1.6b171bb5e3435p-1
Вопрос
Почему Windows на виртуальной машине по-разному обрабатывает двоичный файл при установкена машине с конкретным процессором?
Если посмотреть на различия между процессорами E5-2630 v2 и E5-2630 v3, например , то процессоры дают разные результаты поддерживают инструкции AVX2, F16C и FMA3 Устанавливает, где в качестве прежних процессоров нет.Однако, если бы это и стало причиной расхождений, я бы также подумал, что результаты останутся одинаковыми для Linux и Windows.Кроме того, разборка показала, что используемые регистры были одинаковыми на любом чипе.После отладки файла и пошагового выполнения каждой инструкции вы можете подумать, что поведение будет аналогичным.
Все это подводит итог, вероятно, это различие в архитектуре.Любые мысли о том, как я могу быть уверен?
Ресурсы
Я нашел следующие вопросы несколько полезными в отношении решений продвижения cross-платформа согласованности и получение результатов более детерминированность .Я также долго гулял по сравнению с плавающей точкой и не могу порекомендовать его всем, кто интересуется этой темой.