NO_OF_PROCESSORS
показывает 4, потому что ваш процессор поддерживает технологию Hyper-threading. Hyper-threading — это торговая марка Intel для технологии, которая позволяет одному ядру выполнять 2 потока одного и того же приложения более или менее одновременно. Он работает до тех пор, пока, например. один поток извлекает данные, а другой обращается к ALU. Если обоим требуется один и тот же ресурс, а инструкции нельзя переупорядочить, один поток остановится. Вот почему вы видите 4 ядра, хотя у вас их 2.
То, что динамическая память доступна только для одного из ядер, это IMO не совсем правильно, но содержимое регистра и иногда содержимое кеша. Все, что находится в оперативной памяти, должно быть доступно для всех процессоров.
Может помочь больше потоков, чем ЦП, в зависимости от того, как работает планировщик вашей операционной системы / как вы получаете доступ к данным и т. Д. Чтобы обнаружить это, вам нужно будет сравнить свой код. Все остальное будет просто догадками.
Кроме того, если вы пытаетесь изучить Qt, возможно, об этом не стоит беспокоиться...
Изменить:
Отвечая на ваш вопрос: мы не можем сказать вам, насколько медленнее/быстрее будет работать ваша программа, если вы увеличите количество потоков. В зависимости от того, что вы делаете, это будет меняться. Если вы, например. ожидая ответов из сети, вы можете увеличить количество потоков намного больше. Если все ваши потоки используют одно и то же оборудование, 4 потока могут работать не лучше, чем 1. Лучший способ — просто протестировать свой код.
В идеальном мире, если вы «просто» обрабатываете числа, не должно быть разницы, если у вас запущено 4 или 8 потоков, время работы должно быть одинаковым (без учета времени переключения контекста и т. д.). просто время отклика будет отличаться. Дело в том, что нет ничего идеального, у нас есть кеши, ваши процессоры все обращаются к одной и той же памяти по одной и той же шине, поэтому в итоге они конкурируют за доступ к ресурсам. Кроме того, у вас также есть операционная система, которая может или не может планировать поток/процесс в заданное время.
Вы также запросили объяснение накладных расходов на синхронизацию: если все ваши потоки обращаются к одним и тем же структурам данных, вам придется выполнить некоторую блокировку и т. д., чтобы ни один поток не обращался к данным в недопустимом состоянии во время их обновления.
Предположим, у вас есть два потока, которые делают одно и то же:
int sum = 0; // global variable
thread() {
int i = sum;
i += 1;
sum = i;
}
Если вы запустите два потока, делающих это одновременно, вы не сможете надежно предсказать вывод: это может произойти следующим образом:
THREAD A : i = sum; // i = 0
i += 1; // i = 1
**context switch**
THREAD B : i = sum; // i = 0
i += 1; // i = 1
sum = i; // sum = 1
**context switch**
THREAD A : sum = i; // sum = 1
В конце концов, sum
это 1
, а не 2
, даже если вы начали тему дважды. Чтобы избежать этого, вы должны синхронизировать доступ к sum
, общим данным. Обычно вы делаете это, блокируя доступ к sum
столько времени, сколько необходимо. Накладные расходы на синхронизацию — это время, в течение которого потоки будут ждать, пока ресурс снова не будет разблокирован, ничего не делая.
Если у вас есть отдельные рабочие пакеты для каждого потока и нет общих ресурсов, у вас не должно быть накладных расходов на синхронизацию.
person
Andreas Wallner
schedule
26.01.2013