Java - оптимизировать функцию, которая содержит в основном простые математические - PullRequest
1 голос
/ 11 июля 2011

Я должен попытаться оптимизировать этот метод для своей команды, работающей над видеодекодером на Java, хотя я не вижу никакого хорошего подхода к этому.Приведенная ниже функция, похоже, не может быть ускорена в какой-либо значительной степени, поскольку она содержит в основном простое сложение / вычитание / и т.д.или что бы вы предложили?

Ответы [ 3 ]

1 голос
/ 11 июля 2011

Я не вижу ничего очевидного. В дополнение к тому, что сказал Алекс, есть два небольших предложения, которые могут помочь:

1) Длинный оператор if в первом цикле имеет ряд состояний отказа. Вы заказали его так, чтобы тот, который с наибольшей вероятностью потерпел неудачу, был первым? При оценке короткого замыкания, чем раньше вы сможете найти false, тем меньше работы потребуется для оценки всего выражения.

2) Вы объявляете много переменных вне двух циклов for, и я понимаю, почему вы это сделали. Вполне возможно, что JVM сможет лучше оптимизировать ситуацию, если вы переместите объявления внутри двух циклов, чтобы переменные объявлялись как можно локально.

Для того и другого вам нужно выполнить несколько временных прогонов, чтобы увидеть, действительно ли они имеют значение. Вы также можете использовать профилировщик, чтобы увидеть, где код проводит большую часть своего времени.

У меня есть еще один комментарий. В строках вроде:

data[pointer + 7] = (short) ((tmp10 - tmp3) >> F3);

вы используете >> вместо >>> для сдвига битов возможно отрицательного числа. Вы уверены, что это то, что вы хотите сделать, если tmp3> tmp10?

1 голос
/ 11 июля 2011

Как и другие плакаты, я думаю, что вы очень мало можете сделать, чтобы оптимизировать это как таковое.

Просто из отчаяния, я бы попытался прочитать все значения (dataBlockBuffer [x]) в локальные переменные ДО условия, а затем изменить ваше условие на:

if ((data0 | data1 | data2 | ...) == 0) ...

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

Но, тем не менее, я не думаю, что вы собираетесь сильно сбриться.

Еще одна очень незначительная вещь, которую следует учитывать, заключается в том, что обертывание ByteBuffer вокруг массива позволяет вам потенциально читать / записывать несколько значений одновременно, если вы можете найти способ сделать это. (По крайней мере, когда вы пишете dcValue несколько раз, вместо этого вы можете написать long, если JIT-компилятор не выполнит эту оптимизацию).

На рабочем столе я мог бы подумать:

  • многопоточность для обработки нескольких блоков одновременно (большинство людей в настоящее время имеют как минимум двухъядерные процессоры, но, возможно, не на Android);
  • просматривая JIT-скомпилированный вывод и убедившись, что JIT-компилятор не делает ничего слишком глупого, а затем заново обрабатывает код соответствующим образом (вы можете сделать это с отладочным JDK, но не знаете, есть ли эквивалентный для Android);
  • возможность нативизации, а затем использование графического процессора / любых разумных прагм, которые может понадобиться вашему компилятору C для конкретных SSE / эквивалентных инструкций (я не эксперт в этом и не знаю, насколько это возможно в ваш случай).

В любом случае, я бы посчитал последние два типа «крайними» вариантами - с риском вложения значительного времени для небольшой выгоды.

1 голос
/ 11 июля 2011

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

  1. Заменить повторяющиеся вычисления переменными. Например, pointer+7 повторяется несколько раз. Вы можете рассчитать его один раз.
  2. Используйте System.arraycopy() для копирования массива в конце.
...