Проблема производительности Java для math.abs - PullRequest
2 голосов
/ 27 февраля 2011

Я использую матрицу Джама для выполнения операций SVD. У меня есть пара вопросов относительно производительности.

Меня не беспокоит такая большая точность, и я думаю, что double более точен, чем Float, я прав? Если я использую float, отличный от double, насколько это улучшит производительность и снизит точность?

В матрице Jama используется одна функция, которую она вызывает много, используется функция double и функция Math.abs, которая требует много кучи и процессора. Если я изменю его на удвоение и удалим Math.abs, насколько это повлияет на производительность и результаты с точки зрения точности?

Вот математическая функция Джама:

   public static double hypot(double a, double b) {
      double r;
      if (Math.abs(a) > Math.abs(b)) {
         r = b/a;
         r = Math.abs(a)*Math.sqrt(1+r*r);
      } else if (b != 0) {
         r = a/b;
         r = Math.abs(b)*Math.sqrt(1+r*r);
      } else {
         r = 0.0;
      }
      return r;
   }

Вот что я думаю сделать с этой функцией

   public static float hypot(float a, float b) {
      float r;
      if (a > b) {
         r = b/a;
         r = (float) (a*Math.sqrt(1+r*r));
      } else if (b != 0) {
         r = a/b;
         r = (float) (b*Math.sqrt(1+r*r));
      } else {
         r = 0;
      }
      return r;
   }

Я не знаю, хороший это способ или нет. Спасибо

Ответы [ 2 ]

6 голосов
/ 27 февраля 2011

Я ожидаю, что хороший JIT встроит вызов Math.abs в одну инструкцию. Если ваш код работает на FPU (вполне вероятно), использование float не даст вам никакой скорости, потому что почти все FPU являются 64-битными или лучше.

Однако причина, по которой алгоритм настолько необычен, состоит в том, что он предотвращает переполнение, когда величина его операндов порядка 10 ^ 150. Если вы планируете использовать float, ваши операнды не должны быть величиной больше, чем примерно 10 ^ 38, а это означает, что самый быстрый алгоритм будет просто:

public static double hypot(double a, double b) {
    return Math.sqrt(a * a + b * b);
}
1 голос
/ 27 февраля 2011

Ваш подход не будет работать для отрицательных аргументов. Просто добавьте:

if (a < 0) a = -a;
if (b < 0) b = -b;

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...