вторник, 13 апреля 2010 г.

Эксперимент: Mutex vs MultiCore

Стало мне тут на днях любопытно: а что будет, если я буду синхронизировать очень короткие задачи (мьютекс на входе в контейнер)
Сделал тест: контейнер с примитивом синхронизации и несколько потоков с возможностью привязки к ядру процессора, в качестве примитива был выбран мой любимый tbb::spin_mutex (пробовал boost::mutex результаты удручающиее).

Запустил сначала на своей машине с процессором Pentium 4, выполнил тест без привязки к ядрам, потом все потоки на одно ядро, затем все потоки на разные ядра. Но Pentium 4 всего одно ядро и результаты запусков не особо различались, что не удивительно. Затем решил прогнать тест на Xeon Core 2 Quad (для упрощения маркировок), сначала прогнал тест привязав все потоки на одно ядро для получения эталона производительности при последовательном выполнении, затем без привязки и несколько тестов с различными хитрыми привязками.
Результаты всех запусков чуть ниже.

Все мы знаем, что Core 2 Quad это 2 изолированных Core 2 Duo в одном корпусе, без единого L3 или L2 между ними, есть только L2 на 2 ядра, и естественным было ожидать некоторое пенальти из-за синхронизации кэшей внутри Core 2 Duo или между ними, но что бы всё было настолько грустно, я не ожидал.
Впрочем время работы теста внутри одного Core 2 Duo было вполне сопоставимо с временем на одном ядре. Так же следует отметить, что при выполнении теста ядра на которых выполняли потоки были загружены на 100%, т.е. 4 потока на одном ядре работали X секунд и полностью задействовали 1 ядро, 4 потока на 2-х ядрах отрабатывали за те же X секунд, но использовали уже 2 ядра.

Естественно можно говорить, что в реальной жизни такого не бывает и прочее бла-бла-бла, но цель теста не доказать или показать, как плохи/хороши примитивы, а ответить на вопрос: А что если?

1 комментарий:

  1. Я считаю, что нужно немедленно отправить этот баг-репорт Интелу, чтобы исправили :)
    А если серьёзно, то меня несколько напрягает во втором тесте, когда нет привязки к ядрам. В таком случае (я так раньше думал по-крайней мере), система должна распределять задачи таким образом, чтобы они выполнялись максимально быстро.
    Очевидно, что это не так. Получается, что система распределяет задачи таким образом, чтобы загрузить максимальное кол-во ядер. Ну точнее, она так делает в том случае, когда кол-во задач (потоков) не больше, чем ядер. В связи с этим я бы сделал такие же тесты, как уже сделанные, но с условием, что потоков может быть больше или даже много больше, чем ядер. Что будет тогда? Ну и заодно можно было бы сделать функционал, чтобы каждый поток как-нибудь сообщал о том, на каком ядре он работает.

    ОтветитьУдалить