У меня есть маленький 3D векторный класс в C# 3.0 на основе структуры, которая использует дважды в качестве основной единицы.
Пример: y-значение Одного вектора
-20.0 straight
Я вычитаю вектор с y-значением
10.094999999999965
Значение для y, который я ожидал бы,
-30.094999999999963 (1)
Вместо этого я добираюсь
-30.094999313354492 (2)
Когда я делаю целое вычисление в одном единственном потоке, я добираюсь (1). Также отладчик и возвраты быстрых часов VS (1). Но, когда я выполняю несколько повторений в одном потоке и затем вызываю функцию от другого потока, результат (2). Теперь, возвраты отладчика (2) также!
Мы должны иметь в виду, что JIT.NET мог бы записать значения обратно к памяти (веб-сайт Jon Skeet), который уменьшает точность от 80 битов (FPU) к 64 битам (дважды). Однако точность (2) далека ниже этого.
Векторный класс в основном походит на это
public struct Vector3d
{
private readonly double _x, _y, _z;
...
public static Vector3d operator -(Vector3d v1, Vector3d v2)
{
return new Vector3d(v1._x - v2._x, v1._y - v2._y, v1._z - v2._z);
}
}
Вычисление так легко
Vector3d pos41 = pos4 - pos1;
Да, я считаю, что результат может зависеть от потока.
Я предполагаю, что вы используете DirectX в какой-то момент своего кода - и он устанавливает точность для FPU, и я считаю, что он устанавливает ее для каждого потока.
Чтобы исправить это, используйте флаг D3DCREATE_FPU_PRESERVE при вызове CreateDevice
. Обратите внимание, что это потенциально может повлиять на производительность. Управляемый эквивалент - CreateFlags.FpuPreserve
.
(См. этот связанный вопрос . Я не предлагал закрыть этот как дубликат, поскольку они, по крайней мере, внешне выглядят немного иначе. И то, и другое должно быть помогите найти ответ.)