Почему на 4-х ядерном процессоре происходит эмуляция 12-и ядерного?

Добрый день!
Решил в рамках развлечения поэксперемнтировать с классом thread. И внезапно получил результат, которого не понял.

Собственно, код:

#include "stdafx.h"
#include <thread>
#include <vector>
#include <iostream>
#include <chrono>
#include <mutex>
#include <fstream>

using namespace std;
using namespace chrono;

#define MAX_PROGON 10
#define MAX_THREADS 100000
#define MAX_SLEEPS 10

mutex mtx;

volatile int threadEnd = 0;

void threadDo(int param) {
	int natur = 0;
	for (int i = 0; i < MAX_SLEEPS; i++) {
		for (int x = 2; x < 1000; x++)
		{
			bool sample = true;
			for (int y = 2; y < x; y++)
				if (x % y == 0)
					sample = false;
			if (sample)
				natur += x;
		}
		//if(natur > 0)
			//this_thread::sleep_for(1ms);
	}
	if (natur > 0) {
		mtx.lock();
		threadEnd++;
		mtx.unlock();
	}
	
}

int main(int argc, char**argv)
{
	int startThread = 1;
	string fileName("stats");
	if (argc > 1)
	{
		startThread = atoi(argv[1]);
		fileName += argv[1];
	}
	fileName += ".txt";
	int end;
	ofstream of;
	
	of.open(fileName, ios_base::app);

	for (int ii = startThread; ii < MAX_THREADS; ii++) {
		high_resolution_clock::time_point t1 = high_resolution_clock::now();
		for (int progon = 0; progon < MAX_PROGON; progon++)
		{
			//vector<thread*> allThr;
			for (int i = 0; i < ii; i++)
			{
				thread* thr = new thread(threadDo, i);
				//allThr.push_back(thr);
			}

			while (threadEnd < ii);
			threadEnd = 0;
		}
		high_resolution_clock::time_point t2 = high_resolution_clock::now();
		std::chrono::duration<double, std::milli> elapsed = (t2 - t1) / MAX_PROGON;
		cout << ii << " " << elapsed.count() << " time per thread:" << (elapsed / ii).count() << '\n';
		of << ii << " , " << elapsed.count() << " , time per thread , " << (elapsed / ii).count() << '\n';
		of.flush();
		/*for each (auto var in allThr)
		{
			var->detach();
			delete var;
		}*/
	}
	cin >> end;
	of.close();
    return 0;
}


Вывод:
1 60.7425 time per thread:60.7425
2 69.5908 time per thread:34.7954
3 89.0804 time per thread:29.6935
4 118.862 time per thread:29.7154
5 126.483 time per thread:25.2966
6 113.312 time per thread:18.8854
7 105.037 time per thread:15.0053
8 115.368 time per thread:14.4211
9 113.421 time per thread:12.6023
10 111.08 time per thread:11.108
11 102.801 time per thread:9.34558
12 103.646 time per thread:8.63715
13 107.682 time per thread:8.28321
14 111.319 time per thread:7.95138
15 115.914 time per thread:7.7276
16 131.055 time per thread:8.19092
17 136.007 time per thread:8.00039
18 142.292 time per thread:7.90509
19 146.616 time per thread:7.71661
20 170.397 time per thread:8.51984
21 178.069 time per thread:8.4795
22 172.789 time per thread:7.85407
23 174.325 time per thread:7.57935
24 192.005 time per thread:8.00019

На 12-ом потоке время выполнения потока уменьшается до минимального значения и больше не падает ни на каком потоке, при этом общее выполнение задачи больше не уменьшается ни на одном потоке.
А процессор - 4-х ядерный... i5-5200U.
Кто сможет объяснить этот нюанс?
  • Вопрос задан
  • 886 просмотров
Решения вопроса 1
@Mercury13
Программист на «си с крестами» и не только
1. Такую работу со счётчиком threadEnd лучше делать через std::atomic.
2. В вашем процессоре два гипертредированных ядра, 4 потока.
3. Главный поток ждёт-крутится. «1 поток» — это работают ДВА потока (не забывайте, главный просто крутится). «2 потока» — это ТРИ потока, два настоящих ядра и одно виртуальное — потому результаты не вдвое ниже. Так что вижу локальный минимум на трёх потоках, это верно. У меня на рабочем 8-поточном процессоре, как и полагается, даёт минимум на семи потоках.
4. Условие if (natur > 0) кажется излишним.
5. Вижу большой разброс результатов. То ли таймер недостаточно точный, то ли компьютер загружен кучей посторонней работы — таким результатам доверять не стоит.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы