Дано:
- Полностью процессор привязан к очень большому (т.е. более чем несколько циклов ЦП) и
- Процессор с 4 физическими и всего 8 логическими ядрами,
Возможно ли, что потоки 8, 16 и 28 работают лучше, чем 4 потока? Я понимаю, что 4 потока будут иметь меньшие контекстные переключатели для выполнения и будут иметь меньшие служебные данные в любом смысле, чем 8, 16 или 28 потоков будут иметь на 4-х физических ядрах, Тем не менее, тайминги -
Threads Time Taken (in seconds)
4 78.82
8 48.58
16 51.35
28 52.10
Код, используемый для проверки получения таймингов, указан в разделе Оригинальный вопрос ниже. Спецификации CPU также указаны внизу.
После прочтения ответов, предоставленных различными пользователями, и информации, приведенной в комментариях, я могу, наконец, свести вопрос к тому, что я написал выше. Если приведенный выше вопрос дает вам полный контекст, вы можете пропустить исходный вопрос ниже.
Оригинальный вопрос
Что это значит, когда мы говорим
Работа с гиперпотоками путем дублирования определенных разделов процессор - те, которые хранят архитектурное состояние, но не дублируют основные ресурсы выполнения. Это позволяет использовать процессор с гиперпотоками появляться как обычный "физический" процессор и дополнительный "логический" процессор к операционной системе хоста
?
Этот вопрос задан сегодня на SO, и в основном он проверяет производительность нескольких потоков, выполняющих ту же работу. Он имеет следующий код:
private static void Main(string[] args)
{
int threadCount;
if (args == null || args.Length < 1 || !int.TryParse(args[0], out threadCount))
threadCount = Environment.ProcessorCount;
int load;
if (args == null || args.Length < 2 || !int.TryParse(args[1], out load))
load = 1;
Console.WriteLine("ThreadCount:{0} Load:{1}", threadCount, load);
List<Thread> threads = new List<Thread>();
for (int i = 0; i < threadCount; i++)
{
int i1 = i;
threads.Add(new Thread(() => DoWork(i1, threadCount, load)));
}
var timer = Stopwatch.StartNew();
foreach (var thread in threads) thread.Start();
foreach (var thread in threads) thread.Join();
timer.Stop();
Console.WriteLine("Time:{0} seconds", timer.ElapsedMilliseconds/1000.0);
}
static void DoWork(int seed, int threadCount, int load)
{
var mtx = new double[3,3];
for (var i = 0; i < ((10000000 * load)/threadCount); i++)
{
mtx = new double[3,3];
for (int k = 0; k < 3; k++)
for (int l = 0; l < 3; l++)
mtx[k, l] = Math.Sin(j + (k*3) + l + seed);
}
}
(Я вырезал несколько скобок, чтобы привести код на одной странице для быстрой читаемости.)
Я запустил этот код на своей машине для репликации проблемы. Моя машина имеет 4 физических ядра и 8 логических. Метод DoWork()
в приведенном выше коде полностью связан с ЦП. Я чувствовал, что гиперпоточность может способствовать, возможно, 30% -ному ускорению (потому что здесь у нас так много связанных с процессором потоков как физические ядра (т.е. 4)). Но он почти достигает 64% производительности.. Когда я запускал этот код для 4 потоков, это заняло около 82 секунд, и когда я запускал этот код для 8, 16 и 28 потоков, он выполнялся во всех случаях примерно 50 секунд.
Подводя итоги таймингов:
Threads Time Taken (in seconds)
4 78.82
8 48.58
16 51.35
28 52.10
Я видел, что использование ЦП составляло ~ 50% с 4 потоками. Разве это не должно быть 100%? Ведь у моего процессора всего 4 физических ядра. И использование процессора было ~ 100% для 8 и 16 потоков.
Если кто-то может объяснить цитируемый текст с самого начала, я надеюсь лучше понять его с гиперпотоком и, в свою очередь, надеюсь получить ответ на вопрос: почему бы весь процесс с привязкой к процессору работать лучше с гиперпотоком?
Для завершения,
- У меня есть процессор Intel Core i7-4770 с частотой 3,40 ГГц, 3401 МГц, 4 ядра (я), 8 логических процессоров.
- Я запускал код в режиме Release.
- Я знаю, что время измерения измеряется плохо. Это даст время для самой медленной нити. Я взял код, как и из другого вопроса. Однако, каково оправдание использования 50% CPU при запуске 4 связанных с процессором потоков на 4-х физических ядрах?