Вопрос

Я запускаю массовые параллельные научные вычислительные задания на совмещенном компьютере Linux с 24 ядрами. Большую часть времени мои рабочие места способны масштабироваться до 24 ядер, когда на этом компьютере ничего не работает. Тем не менее, похоже, когда даже одна однопоточная работа не работает, мои 24-нить задания (которые я устанавливаю для высоких приятных значений), только удается получить ~ 1800% CPU (с использованием записи Linux). Между тем, около 500% циклов ЦП (опять же, используя нотацию Linux), простаивают. Может кто-нибудь объяснить это поведение и то, что я могу сделать с этим, чтобы получить все 23 ядра, которые не используются кем-то другим?

Примечания:

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

  2. Архитектура процессора X64. Это вообще возможно, что тот факт, что мои 24-я-ядерные задания 32-разрядные, а другие задания, которые я конкурирую с 64-битным, имеет отношение?

Редактировать: Одна вещь, которую я только что заметил, это то, что до 30 нитей, кажется, облегчает проблему до некоторой степени. Это заставляет меня до ~ 2100% CPU.

Это было полезно?

Решение

Возможно, что это вызвано планировщиком, пытаясь сохранить каждую из ваших задач, работающих на том же процессоре, что она ранее работала на (это делает это, потому что задача, вероятно, принесла свою работу, установленную в кэш CPU - это «кэш горячим ").

Вот несколько идей, которые вы можете попробовать:

  • Пробежать в два раза больше потоков, так как у вас есть сердечники;
  • Запустить одну или две меньше потоков, чем у вас сердечники;
  • Уменьшить ценность /proc/sys/kernel/sched_migration_cost (возможно, до нуля);
  • Уменьшить ценность /proc/sys/kernel/sched_domain/.../imbalance_pct вниз ближе к 100.

Другие советы

Ваши темы должны синхронизировать? Если это так, у вас может быть следующая проблема:

Предположим, у вас есть система 4-процессора, а также 4-пототное задание. Когда бегите в одиночку, нити вентилируются, чтобы использовать все 4 ядра, а полное использование близко (мы назовем это 400%).

Если вы добавите одну однопоточную мешающую задание, планировщик может разместить 2 ваших потоков на тот же процессор CPU. Это означает, что 2 ваших потоков теперь действуют в результате эффективной половины их обычного темпа (драматическое упрощение), и если ваши потоки должны периодически синхронизировать, прогресс вашей работы может быть ограничен самым медленным потоком, который в этом случае работает в половина нормальной скорости. Вы бы увидели использование только 200% (с вашей работы 4X 50%) плюс 100% (мешающая задание) = 300%.

Точно так же, если вы предполагаете, что вмешательство использует только 25% одного процессора, вы можете увидеть одну из ваших потоков и интерференции на том же процессоре. В этом случае самая медленная нить работает на 3/4 нормальной скорости, вызывая общее использование на 300% (4х 75%) + 25% = 325%. Играйте с этими числами, и не сложно придумать что-то похожее на то, что вы видите.

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

Ваши темы общаются друг с другом?

Попробуйте вручную связать каждую нить в CPU, с sched_setaffinity или pthread_setaffinity_np. Отказ Планировщик может быть довольно тупой при работе со многими связочными нитями.

Это может быть полезно использовать mpstat (часть sysstat Пакет), чтобы выяснить, если у вас есть целые процессоры сидя на холостом ходу, в то время как другие полностью используются. Это должно дать вам более подробный вид на использование, чем верх или VMStat: Run mpstat -P ALL Чтобы увидеть 1 строку на CPU.

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

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

// COMPILE WITH: gcc threads.c -lpthread -o thread
#include <pthread.h>
#define NUM_CORES 24

void* loop_forever(void* argument) {
    int a;
    while(1) a++;
}

void main() {
    int i;
    pthread_t threads[NUM_CORES];

    for (i = 0; i < NUM_CORES; i++)
        pthread_create(&threads[i], 0, loop_forever, 0);

    for (i = 0; i < NUM_CORES; i++)
        pthread_join(threads[i], 0);
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top