Улучшение производительности сетевого кодирования-кодирования - PullRequest
4 голосов
/ 12 октября 2011

В настоящее время я разрабатываю библиотеку на основе Java для сетевого кодирования (http://en.wikipedia.org/wiki/Network_coding). Это очень сильно загружает процессор и поэтому нуждается в некоторой помощи в оптимизации этапа кодирования. Что я по сути делаю, так это создание случайных линейные комбинации исходных данных, где сложение - XOR, а умножение - умножение поля Галуа (в GF (2 ^ 16)).

Я дошел до того, что способен на оптимизацию. Например, я использую такие трюки: http://groups.google.com/group/comp.dsp/browse_thread/thread/cba57ae9db9971fd/7cd21eec39ddae1a?hl=en&lnk=gst&q=Sarwate+Galois#7cd21eec39ddae1a для ускорения умножения.

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

Более конкретно, некоторые потенциальные области улучшения, по которым мне нужна помощь:

  • Как я могу убедиться, что Java может пропустить проверку границ для операций с массивами?
  • Как я могу получить байт-код, который фактически выполняется после оптимизации HotSpot?

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

int messageFragmentStart = 0;
int messageFragmentEnd = fragmentCharSize;

int coefficientIndex = fragmentID * messageFragmentsPerDataBlock;
final int resultArrayIndexStart = fragmentID * fragmentCharSize;

for (int messageFragmentIndex = 0; messageFragmentIndex < messageFragmentsPerDataBlock; messageFragmentIndex++) {
    final int coefficientLogValue = coefficientLogValues[coefficientIndex++];
    int resultArrayIndex = resultArrayIndexStart;
    for (int i = messageFragmentStart; i < messageFragmentEnd; i++) {
        final int logSum = coefficientLogValue + logOfDataToEncode[i];
        final int messageMultipliedByCoefficient = expTable[logSum];                        
        resultArray[resultArrayIndex++] ^= messageMultipliedByCoefficient;
    }
    messageFragmentStart += fragmentCharSize;
    messageFragmentEnd = Math.min(messageFragmentEnd + fragmentCharSize, maxTotalLength);
}

1 Ответ

2 голосов
/ 12 октября 2011

Вы не можете заставить Java отказаться от проверки границ, как указано в JLS.Но в большинстве случаев JIT может избежать этого, если проверка границ проста (например, i < array.length) - если нет, то нет способа избежать этого (хорошо, я предполагаю, что можно играть с небезопасными объектами?).

Для вашей второй проблемы здесь есть это , которое должно отлично выполнять поставленные цели.

Но в любом случае из вашего кода кажется, что эта проблема тривиальна для векторизации, и, к сожалению, JVM нене очень хорош в этом / делает это вообще.Следовательно, реализация того же кода в c / c ++ с использованием встроенных функций компиляции (вы даже можете попробовать автоматическую векторизацию ICC / GCC) может привести к довольно заметным ускорениям - при условии, что мы не полностью ограничены памятью.Поэтому я реализовал бы это в C ++ и использовал бы JNI только для справки.

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