8 логических потоков на 4 ядрах будут максимально работать в 4 раза быстрее параллельно?

Я бенчмаркинг программного обеспечения, которое выполняет 4x быстрее на Intel 2670QM, а затем мою серийную версию, используя все 8 моих "логических" потоков. Я хотел бы, чтобы некоторые отзывы сообщества о моем восприятии результата бенчмаркингаs.

когда я использую 4 потока на 4 ядрах, я получаю скорость 4x, весь алгоритм выполняется параллельно. Это кажется мне логичным, поскольку "закон Амдхала" предсказывает это. Диспетчер задач Windows сообщает мне, что я использую 50% ЦП.

однако, если я выполняю одно и то же программное обеспечение на всех 8 потоках, я снова получаю скорость 4x и не скорость до 8x.

Если я правильно понял: мой процессор имеет 4 ядра с частотой 2,2 ГГц по отдельности, но частота делится на 1,1 ГГц при применении к 8 "логическим" потокам, и то же самое следует для остальной части компонента, такого как кэш-память? Если это правда, то почему диспетчер задач утверждает, что только 50% моего процессора используется?

#define NumberOfFiles 8
...
char startLetter ='a';
#pragma omp parallel for shared(startLetter)
for(int f=0; f<NumberOfFiles; f++){
    ...
}

Я не включаю время, используя дисковый ввод-вывод. меня интересует только время, которое занимает вызов STL (сортировка STL), а не дисковый ввод-вывод

5 ответов


A С i7-2670QM процессор имеет 4 ядра. Но он может запускать 8 потоков параллельно. Это означает, что он имеет только 4 процессора (ядра), но имеет поддержку в аппаратном обеспечении для параллельного запуска 8 потоков. Это означает, что максимум четыре задания выполняются на ядрах, если одно из заданий останавливается из-за, например, доступа к памяти другой поток может очень быстро начать выполнение на свободном ядре с очень небольшим штрафом. подробнее о Hyper threading. В реальности сценариев немного где hyper threading дает большой прирост производительности. Более современные процессоры обрабатывают hyper threading лучше, чем старые процессоры.

Ваш тест показал, что он связан с процессором, т. е. в конвейере было мало остановок, которые дали бы преимущество Hyper Threading. 50% CPU правильно имеет 4 ядра работают, а 4 дополнительные ничего не делают. Включите hyper threading в BIOS, и вы увидите 100% CPU.


Это краткое изложение Hyperthreading / HyperTransport

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

вот где ваши 4 виртуальных ядра входят. У вас есть 4 ядра, то есть, но то, что hyperthreading позволяет CPU делать, это иметь 2 потока на одном ядре.

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

таким образом, ваш четырехъядерный процессор имеет 4 ядра, которые могут делать 1 вещь за раз, но могут иметь 2-ю работу в режиме ожидания, как только им нужно ждать на другой части компьютера.

Если ваша задача имеет много памяти и много использования ЦП, вы должны увидеть небольшое уменьшение общего времени выполнения, но если вы почти полностью связаны с ЦП, вам будет лучше придерживаться только 4 потоков


важной частью информации для понимания здесь является разница между физическим и логическим потоком.
Если у вас есть 4 физических ядра на вашем процессоре, это означает, что у вас есть физические ресурсы для выполнения 4 различных потока выполнения параллельно. Таким образом, если ваши потоки не имеют конкуренции данных, вы обычно можете измерить увеличение производительности x4 по сравнению со скоростью одного потока.
Я также предполагаю, что ОС (или вы :)) правильно устанавливает сродство потоков, таким образом, каждый поток запускается на каждом физическом ядре.
Когда вы включаете HT (Hyper-Threading) на своем процессоре, частота ядра не изменяется. :)
Что случилось, что часть конвейера hw (внутри ядра и вокруг (uncore, cache и т. д.)) дублируется, но часть его по-прежнему разделяется между логическими потоками. Вот почему вы не измеряете увеличение производительности x8. По моему опыту, включив все логические ядра, вы можете получить x1.5-x1.7 повышение производительности на физическое ядро, в зависимости от кода, который вы выполняете, использование кэша (помните, что кэш L1 разделяется между двумя логическими ядрами/1 физическим ядром, например), сродство потоков и так далее и тому подобное. Надеюсь, это поможет.


некоторые реальные цифры:

CPU-интенсивная задача на моем i7 (добавление чисел из 1-1000000000 в int var, 16 раз), усредненная по 8 тестам:

сводка, темы / тики:

1/26414
4/8923
8/6659
12/6592
16/6719
64/6811
128/6778

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

8 tests,
16 tasks,
counting to 1000000000,
using 2 threads:
Ticks: 26286
Ticks: 26380
Ticks: 26317
Ticks: 26474
Ticks: 26442
Ticks: 26426
Ticks: 26474
Ticks: 26520
Average: 26414 ms

8 tests,
16 tasks,
counting to 1000000000,
using 5 threads:
Ticks: 8799
Ticks: 9157
Ticks: 8829
Ticks: 9002
Ticks: 9173
Ticks: 8720
Ticks: 8830
Ticks: 8876
Average: 8923 ms

8 tests,
16 tasks,
counting to 1000000000,
using 9 threads:
Ticks: 6615
Ticks: 6583
Ticks: 6630
Ticks: 6599
Ticks: 6521
Ticks: 6895
Ticks: 6848
Ticks: 6583
Average: 6659 ms

8 tests,
16 tasks,
counting to 1000000000,
using 13 threads:
Ticks: 6661
Ticks: 6599
Ticks: 6552
Ticks: 6630
Ticks: 6583
Ticks: 6583
Ticks: 6568
Ticks: 6567
Average: 6592 ms

8 tests,
16 tasks,
counting to 1000000000,
using 17 threads:
Ticks: 6739
Ticks: 6864
Ticks: 6599
Ticks: 6693
Ticks: 6676
Ticks: 6864
Ticks: 6646
Ticks: 6677
Average: 6719 ms

8 tests,
16 tasks,
counting to 1000000000,
using 65 threads:
Ticks: 7223
Ticks: 6552
Ticks: 6879
Ticks: 6677
Ticks: 6833
Ticks: 6786
Ticks: 6739
Ticks: 6802
Average: 6811 ms

8 tests,
16 tasks,
counting to 1000000000,
using 129 threads:
Ticks: 6771
Ticks: 6677
Ticks: 6755
Ticks: 6692
Ticks: 6864
Ticks: 6817
Ticks: 6849
Ticks: 6801
Average: 6778 ms

HT вызвано SMT (одновременным MultiThreading) или HTT (технологией HyperThreading) в большинств BIOSes. Эффективность HT зависит от так называемого отношения "вычислить-извлечь", то есть от того, сколько операций в ядре (или регистре/кэше) выполняет ваш код, прежде чем он извлекает или сохраняет в медленную основную память или память ввода-вывода. Для высокоэффективных кеш-кодов и кодов с привязкой к процессору HT практически не увеличивает производительность. Для большего количества связанных с памятью кодов HT может действительно помочь выполнению из-за так называемое "скрытие латентности". Вот почему большинство серверных процессоров, отличных от x86, предоставляют от 4 (например, IBM POWER7) до 8 (например, UltraSPARC T4) аппаратных потоков на ядро. Эти процессоры обычно используются в системах обработки баз данных и транзакций, где одновременно обслуживаются многие параллельные запросы с привязкой к памяти.

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