Возможно ли повышение производительности при использовании JNI? - PullRequest
2 голосов
/ 20 апреля 2011

Год или два назад я создал программу, написанную на Java, для имитации задачи n-body.Недавно я получил сумасшедшую идею переписать программу как распределенную программу, чтобы иметь возможность имитировать большие массы с большей точностью.

Профилирование старой программы показало, как и ожидалось, что примерно 90% программы былопровел расчет значений типа float.Если я правильно помню, C / C ++ намного быстрее, чем Java при выполнении арифметических операций, особенно вычислений с плавающей запятой.

В любом случае, вот фактический вопрос:)

Используя JNI, могу ли я ожидать увеличения скорости, равного программе, написанной на C / C ++ (для вычислений), или JVM замедлитсяэто вниз?

Ответы [ 5 ]

5 голосов
/ 20 апреля 2011

Большинство операций с плавающей запятой в Java занимают около 1 нс, поэтому я не уверен, насколько быстрее вы ожидаете их выполнения в C ++.

Однако вызовы JNI часто занимают около 30 нс, поэтому, если вы не выполняете много операций с плавающей запятой за вызов, вы будете стоить больше, чем экономите.

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

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

public static void main(String[] args) throws Exception {
    int length = 200000;
    double[] a = fill(new double[length]);
    double[] b = fill(new double[length]);
    double[] c = fill(new double[length]);
    double[] x = new double[length];

    for (int i = 0; i < 10; i++)
        testTime(length, a, b, c, x);
}

private static void testTime(int length, double[] a, double[] b, double[] c, double[] x) {
    long start = System.nanoTime();
    for (int i = 0; i < length; i++)
        x[i] = a[i] * b[i] + c[i];
    long time = System.nanoTime() - start;
    System.out.printf("Average time per double operation was %.1f ns%n", time / 2.0 / length);
}

private static double[] fill(double[] doubles) {
    for (int i = 0; i < doubles.length; i++)
        doubles[i] =  Math.random();
    return doubles;
}

печать

Average time per double operation was 10.9 ns
Average time per double operation was 17.9 ns
Average time per double operation was 1.7 ns
Average time per double operation was 1.0 ns
Average time per double operation was 0.9 ns
Average time per double operation was 0.8 ns
Average time per double operation was 0.9 ns
Average time per double operation was 0.8 ns
Average time per double operation was 1.0 ns
Average time per double operation was 0.9 ns
3 голосов
/ 20 апреля 2011

Я думаю, что ответ: JNI Performance также применяется здесь. Если вы звоните в JNI много раз и выполняете несколько вычислений каждый раз, ваша производительность должна снизиться. Если вы вызываете JNI для тяжелых вычислений, то оптимизированный для Си код должен работать быстрее.

2 голосов
/ 20 апреля 2011

Самое главное, что касается производительности, - это тестирование и тестирование. Вы слышали, что C ++ лучше с плавающей точкой, чем Java. Хорошо, это может быть так. Но без скамейки, чтобы показать эту фактическую разницу, это не стоит ни копейки. Это может быть действительно ложным.

На самом деле современные Java используют JIT. Что это такое ? Ну, мы все знаем, что Java использует байт-код и что байт-код интерпретируется. Это правда и ложь. На самом деле интенсивно используемый код компилируется на лету в собственный код, оптимизированный для вашей платформы. JIT может даже выполнить оптимизацию, невозможную в C / C ++, используя статистику выполнения.

Теперь Java и JVM широко признаны в качестве действительно быстрой и эффективной платформы. Люди начинают использовать его в тяжелых вычислительных средах с большим успехом. Это также легче развернуть на сетке.

Недавние тесты показывают производительность, аналогичную C / C ++ (например, http://blogs.oracle.com/amurillo/entry/java_vs_c)

Так что вы выиграете от JNI и просто портируете на C ++. Я бы сказал, нет, или очень мало выгоды. (Но снова проверьте, хотите ли вы быть уверенным). И без оптимизации версия C ++ может быть медленнее.

Не могли бы вы добиться значительного улучшения, используя JNI и оптимизированный код сборки (включая инструкции SEE)? Определенно да, если вы делаете это правильно. На это потребовалось бы много скамей, опыта и времени.

2 голосов
/ 20 апреля 2011

Я на самом деле недавно протестировал генерацию фракталов (Мандельброта) с тем же кодом, написанным на Java, а затем портирован на C, и, к моему удивлению, я наблюдал небольшое УМЕНЬШЕНИЕ скорости вычислений при использовании метода JNI.Я могу объяснить это явление только одной вещью: если вы используете код на языке c, вы не сможете воспользоваться преимуществами оптимизации HotSpot для повторяющихся вычислений.

Вы можете самостоятельно проверить пример кода по адресу: http://code.google.com/p/frgenjava/

РЕДАКТИРОВАТЬ: в ситуации, которую я описал, при использовании JNI я игнорирую накладные расходы для вызова JNI, который занимал около 20 нс для вызова, и даже тогда C работал медленнее.

1 голос
/ 20 апреля 2011

Я не могу комментировать скорость арифметических операций Java, но я знаю, что JNI будет напрямую вызывать ваш код C ++, так что вы получите собственную скорость, да

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