Java автоматически распараллеливает рекурсивные функции? - PullRequest
0 голосов
/ 08 ноября 2018

Я распараллеливаю рекурсивную функцию и измерил плохое ускорение. При отладке кода я заметил, что в последовательной версии все ядра работают.

Я воспроизвел это поведение в минимальном примере, и опять-таки, все мои ядра загружены примерно на 90%. Я использую Java 8 (OpenJDK).

Java автоматически выполняет параллелизм без моего ведома? Как это делает Java?

import java.util.Random;
import java.util.ArrayList;

class Node
{
    float value;
    ArrayList<Node> children;

    public Node()
    {
        children = new ArrayList<Node>();
    }

    public Node(float value)
    {
        this.value = value;
    }

    public int count()
    {
        int count = 1;

        if (children != null)
            for (Node c : children)
                count += c.count();

        return count;
    }
}

public class ProofOfConcept {
    final static int N_NODES = 10000000;
    final static int MAX_CHILDREN = 6;

    final static Random RAND = new Random();

    static Node generateTree(int nNodes)
    {
        if (nNodes > 1)
        {
            Node result = new Node();
            int nChildren = 1 + RAND.nextInt(Math.min(MAX_CHILDREN, nNodes) - 1);
            int nNodesPerChild = (nNodes - 1) / nChildren;

            for (int i = 0; i < nChildren; ++i)
            {
                Node t = generateTree(nNodesPerChild);
                result.children.add(t);
            }

            return result;
        }
        else
            return new Node(RAND.nextFloat());
    }

    public static void main(String[] args)
    {
        Node t = generateTree(N_NODES);
        System.out.println(t.count());
    }
}

РЕДАКТИРОВАТЬ: Это также очень странно для меня. Я прилагаю скриншот htop; как видите, у нас есть основной процесс и восемь потоков (по одному на каждое из моих логических ядер).

htop

РЕДАКТИРОВАТЬ 2: Кажется, что GC выполняет свою работу параллельно. Для тех, кто не понимает, почему GC запускается, если очевидно, что никакие объекты не освобождаются, вы должны прочитать следующую ссылку :

Когда сборщик мусора запускается из-за сбоя выделения, но сборщик мусора не освобождает достаточно места, сборщик мусора расширяет кучу хранилища. Во время расширения кучи сборщик мусора извлекает хранилище из максимального объема хранилища, зарезервированного для кучи (объем, указанный параметром -Xmx), и добавляет его в активную часть кучи (которая начинается с размера, указанного в параметре - Вариант хмс). Расширение кучи не увеличивает объем памяти, требуемый для JVM, поскольку максимальный объем памяти, указанный параметром -Xmx, уже был выделен JVM при запуске. Если значение параметра -Xms обеспечивает достаточное хранилище в активной части кучи для ваших приложений, сборщик мусора вообще не должен выполнять расширение кучи.

1 Ответ

0 голосов
/ 08 ноября 2018

Нет, Java волшебным образом не делает ваш код параллельным.

Если вы видите 90% -ное использование на всем ядре, то это либо операционная система, либо другие процессы или JVM, выполняющие фоновую работу. Это может быть JVM, использующая Parallel GC, использующую все ядра для сбора мусора.

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