Использование двухъядерного процессора с одним потоком Java

Возможный дубликат:
Будет ли многопоточное Java-приложение очень хорошо использовать многоядерный компьютер?

У меня есть простой и понятный поток Java, подобный этому, работающий на моей двухъядерной машине (32-битная среда Windows XP)

public static void main(String[] strs) {

    long j  = 0;
    for(long i = 0; i<Long.MAX_VALUE; i++)
        j++;

    System.out.println(j);
    }

Я ожидал, что он будет придерживаться одного процессора, чтобы полностью использовать высокоскоростной кеш (поскольку в цикле мы продолжаем работать с локальной переменной j, следовательно, одно использование ЦП будет 100%, а другое будет в значительной степени простаивать. мой сюрприз, оба процессора используются примерно на 40%~60% после запуска потока, и загрузка одного процессора немного выше, чем другого.

Мой вопрос заключается в том, существует ли какой-либо механизм балансировки нагрузки ОС, который срабатывает при обнаружении дисбаланса? В моем случае, возможно ли, что ОС Windows обнаружит, что один процессор работает почти на 100%, а другой почти бездействует, поэтому он периодически перепланирует поток на другой процессор?

# EDIT1 Я нашел возможное объяснение: http://siber.cankaya.edu.tr/ozdogan/OperatingSystems/ceng328/node130.html

3 ответа

Решение

Когда ОС выполняет потоки, она запускает каждый поток в течение определенного периода времени (скажем, 10-20 мс), затем сохраняет состояние потока и ищет другие потоки для запуска.

Теперь, несмотря на то, что вы можете подумать, посмотрев на график использования ЦП, на самом деле ОС запускает намного больше потоков, чем потоков из вашей программы. Существуют потоки, выполняющие циклы пользовательского интерфейса, потоки, ожидающие ввода-вывода, потоки, выполняющие фоновые службы и т. Д. Большинство потоков проводят большую часть своего времени в ожидании чего-либо.

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

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

Это кажется разумным компромиссом: если ваш поток работает лучше, когда привязан к ядру, просто попросите ОС сделать это. Но ОС не будет пытаться выяснить это для вас.

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

int main( int argc, char** argv )
{
    while( true );
    return 0;
}

Если вы посмотрите на процесс, он постоянно на 25% (с использованием четырехъядерного процессора), но монитор ресурсов из Windows 7 показывает, что ни одно из 4 ядер не имеет постоянных 100%, хотя ядро ​​0 используется более интенсивно, чем другие.

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

Другие вопросы по тегам