2013-03-12 4 views
1

Увеличивается время CPU (как сообщается командой time CLI), указывающее на неэффективность при использовании гиперпотока (например, время, затрачиваемое на прокрутки или промахи в кэше), или возможно, что время процессора раздувается нечетным характером HT? (например, реальные ядра заняты, а HT не может ударить)Является ли время процессора релевантным для Hyperthreading?

У меня четырехъядерный i7, и я тестирую тривиально-параллелизуемую часть (переопределение изображения на палитру) OpenMP program - без блокировок, без критических разделы. Все потоки получают доступ к некоторой части памяти общего доступа только для чтения (справочная таблица), но записываются только в их собственную память.

cores real CPU 
    1: 5.8 5.8 
    2: 3.7 5.9 
    3: 3.1 6.1 
    4: 2.9 6.8 
    5: 2.8 7.6 
    6: 2.7 8.2 
    7: 2.6 9.0 
    8: 2.5 9.7 

Я обеспокоен тем, что количество процессорного времени используется быстро растет, как количество ядер превышает 1 или 2.

Я полагаю, что в идеальном сценарии CPU время не увеличится много (то же самое количество работа просто распределяется по нескольким ядрам).

Означает ли это, что 40% накладных расходов потрачено на распараллеливание программы?

+0

Не забывайте, что сверхпрочные сердечники не являются «настоящими» сердечниками.Поэтому ожидается, что время процессора возрастет. – Mysticial

+1

Я был бы более обеспокоен тем, что количество процессорного времени ** не увеличится быстро, показывая, что ядра не работают. В идеальном случае процессорное время будет 'cores' раз' real' (с 'cores' до' 4', до выхода HT). Вы снижаете эффективность до 65% с 3 ядрами. См. [Закон Амдаля] (http://en.wikipedia.org/wiki/Amdahl%27s_law) о том, как количество непараллельных частей в программе влияет на его масштабируемость. Также проверьте, связана ли проблема с памятью. –

+0

Возможно также, что вы неправильно закодировали раздел «тривиально параллелизуемый». Это очень просто, чтобы заставить параллельные вычисления ошибочно и в конечном итоге тратить производительность, что приводит к субоптимальному масштабированию. Но 40% звучат абсурдно - я легко получаю 95% -ную эффективность с менее масштабируемыми алгоритмами, поэтому здесь определенно что-то играет. – Thomas

ответ

1

Это, возможно, артефакт о том, как измеряется время процессора. Тривиальный пример: если вы запускаете процессор на частоте 100 МГц и процессор 3 ГГц на одну секунду, каждый будет сообщать, что он работал в течение одной секунды. Второй процессор может работать в 30 раз больше, но требуется одна секунда.

С гиперпотоком разумная (не совсем точная) модель будет заключаться в том, что одно ядро ​​может запускать либо одну задачу, либо, скажем, 2000 МГц, или две задачи, скажем, 1200 МГц. Выполняя две задачи, он выполняет только 60% работы на поток, но 120% работы для обоих потоков вместе, улучшается на 20%. Но если ОС спрашивает, сколько секунд времени процессора было использовано, первая сообщит «1 секунду» после каждой секунды в реальном времени, а вторая сообщит «2 секунды».

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

1

Быстрый вопрос - вы используете подлинную программу времени/usr/bin/time или встроенную команду bash с тем же именем? Я не уверен, что это важно, они очень похожи.

Посмотрите на свою таблицу чисел. Я чувствую, что обработанный набор данных (т. Е. Ввод плюс все данные) достаточно большой в целом (больше, чем кэш L2) и что обработка на элемент данных не такая уж длинная.

Цифры показывают почти линейное улучшение от 1 до 2 ядер, но это значительно уменьшает время, когда вы используете 4 ядра. Хиоровые ядра практически ничего не добавляют. Это означает, что за что-то борются. В вашей программе есть свободные потоки, так что это может быть только память (кеш L3 и основная память на i7).

Это звучит как типичный пример привязки ввода-вывода, а не вычисления, причем ввод/вывод в этом случае относится к/из кеша L3 и основной памяти. Кэш L2 составляет 256 тыс., Поэтому я предполагаю, что размер ваших входных данных плюс один набор результатов и все промежуточные массивы больше 256 тыс.

Я рядом с маркой?

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

+0

'/ usr/bin/time' - это то же самое. Мне нравится концепция, но я не знаю, где/если я нахожусь на пределе. [Переназначение] (https://github.com/pornel/improved-pngquant/blob/lib/lib/libimagequant.c#L660) использует таблицу поиска (точный размер зубчатого массива) размером ~ 20 КБ. Полное изображение может иметь размер MB, но доступ к нему осуществляется линейно ('* dest ++ = lookup (* srC++)'). Можете ли вы порекомендовать технику/инструмент, способный выявить разногласия? – Kornel

+0

VTune от Intel Я думаю, вы можете много рассказать о том, что происходит внутри вашей программы (стоит денег, хотя). Однако я думаю, что вы ответили на него «Полный образ может быть размером MB». Это слишком велико для кэшей L2. Вы работаете на нем небольшие куски за раз? Ну, даже если каждый кусок вписывается в L2, кешу все равно придется вытолкнуть результаты на L3, чтобы освободить место для новых кусков результатов. Со всеми четырьмя кэшами L2, пытающимися сделать это все сразу, L3 становится узким местом. И если вы переполняете L3, то он возвращается в основную память. – bazza

+0

Вы можете улучшить ситуацию, если можете подумать о том, что нужно делать на каждом фрагменте, пока он находится в кеше L2/L1. То есть, если после переназначения вы сделаете еще какое-то другое вычисление на изображении, то, возможно, элементы этого могут быть сделаны на куске сразу после переназначения этого фрагмента. Это приведет к возврату баланса из привязки ввода-вывода (вашей текущей ситуации) для вычисления привязки. – bazza

Смежные вопросы