2015-01-15 2 views
1

На основании this вопрос, у меня есть класс, где его конструктор выполняет только некоторые назначения, а затем есть функция build(), которая фактически выполняет задание.Сколько потоков я должен создать?

Я знаю, что количество объектов, которые мне нужно будет построить, находится в диапазоне [2, 16]. Фактическое число - это пользовательский параметр.

Я создаю свои объекты в цикле, как этот

for (int i = 0; i < n; ++i) { 
    roots.push_back(RKD<DivisionSpace>(...)); 
} 

, а затем в другой цикл я создаю темы. Каждый поток вызывает build() в куске объектов, на основе этой логики:

Если вектор имеет п элементы и у вас есть р тема, нити я пишет только к элементам

[в/р (i + 1) n/p).

Так, например, ситуация такова:

std::vector<RKD<Foo>> foos; 
// here is a for loop that pushes back 'n' objects to foos 

// thread A   // thread B     // thread C 
foos[0].build(); foos[n/3 + 0].build(); foos[2 * n/3 + 0].build(); 
foos[1].build(); foos[n/3 + 1].build(); foos[2 * n/3 + 1].build(); 
foos[2].build(); foos[n/3 + 2].build(); foos[2 * n/3 + 2].build(); 
...     ...       ... 

Подход я следовал том, чтобы определить количество потоков p так:

p = min(n, P) 

, где n - количество объектов, которые я хочу создать, и P - возвращаемое значение std::thread::hardware_concurrency. После dealing с некоторыми вопросами, что C++ 11 имеет особенность, я прочитал это:

Даже когда hardware_concurrency реализован, он не может полагаться в качестве прямого отображения на количество ядер. Это то, что стандарт говорит, что он возвращает - количество контекстов аппаратных потоков. И переходит в состояние. Это значение следует рассматривать только как подсказку. Если на вашем компьютере включена гиперпоточность, вполне возможно, что возвращаемое значение будет равно 2x числу ядер. Если вам нужен надежный ответ, вам нужно будет использовать любые средства, предоставляемые вашей ОС. - Praetorian

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

+0

Я не думаю, что котировка вы предоставили означает, что необходимо изменить подход; он говорит только, что это значение может быть числом * логических * (или * виртуальных *) ядер, что хорошо - вы * хотите * воспользоваться гиперпотоком, если он включен. Нет смысла использовать половину количества потоков, если ваш процессор может работать в два раза больше параллельно. – bogdan

+0

@bogdan, если бы вы могли сделать ответ, анализируя вашу точку, это было бы здорово, так как теперь мне не совсем ясно:/ – gsamaras

+0

OpenMP определяет [ряд переменных среды] (https://gcc.gnu.org/onlinedocs /libgomp/Environment-Variables.html), который может, среди прочего, использоваться для выбора максимального количества потоков, которые он будет создавать. Вы можете сделать так, чтобы ваше приложение проверило аналогичные имена переменных, и если они не установлены пользователем, вернитесь к 'std :: thread :: hardware_concurrency'. Это то, что я, вероятно, сделаю. – 5gon12eder

ответ

1

Просто выберите пул потоков из hardware_concurrency потоков и оставьте предметы в порядке поступления, обслуживания.

Если другие процессы в системе каким-то образом получают приоритет от ОС, пусть будет так. Это просто означает, что меньше, чем назначенный размер пула (например, P - 1) может выполняться одновременно. Не имеет значения, так как первый доступный поток пула, который делается build() -в один элемент выберет следующий элемент из очереди.

Чтобы действительно избежать тема конкурирующихов за то же ядро, вы можете

  • использовать семафор (межпроцессный семафор, если вы хотите на самом деле скоординировать строитель нить из отдельных процессов)

  • нити сродства (для предотвращения того, чтобы ОС планировала конкретный поток на другое ядро ​​на следующий срез времени); к сожалению, я не думаю, что есть стандарт, независимый от платформы, способ установить сходство потоков (пока).

Я не вижу никаких веских причин, чтобы сделать его более сложным

+0

«Просто выберите пул потоков потоков hardware_concurrency». Вы имеете в виду пул 'std :: thread' с размером, равным возвращаемому значению hardware_concurrency? – gsamaras

+0

Да. См. здесь http://stackoverflow.com/questions/22569805/boost-thread-throwing-exception-thread-resource-error-resource-temporarily-una/22570554#22570554 («Сумасшедший бонус в пятницу») – sehe

+0

В этом примере используется boost, которого я хочу избежать, но я понимаю эту концепцию. Итак, каждый поток принимает только один элемент, не более одного, как в моем вопросе выше, правильно? – gsamaras