2013-04-04 3 views
6

Я использую visual studio 2012. У меня есть модуль, где мне нужно прочитать огромный набор файлов с жесткого диска после прохождения их соответствующих путей через xml. Для этого я делаюКак обеспечить, чтобы std :: thread были созданы в многоядерном?

std::vector<std::thread> m_ThreadList; 

В цикле, пока я отодвигая новую нить в этот вектор, что-то вроде

m_ThreadList.push_back(std::thread(&MyClass::Readfile, &MyClassObject, filepath,std::ref(polygon))); 

My C++ 11 мульти знаний заправочного является limited.The вопроса У меня есть, есть, как создать поток на конкретном ядре? Я знаю о parallel_for и parallel_for_each в vs2012, которые оптимально используют ядра. Но есть ли способ сделать это, используя стандартный C++ 11?

+0

Функции потока C++ не знают о «ядрах», и поэтому вы не можете привязать поток к определенному ядру. –

+0

Я действительно не знаю, но я угадываю ['SetThreadAffinityMask'] (http://msdn.microsoft.com/en-us/library/ms686247 (v = vs.85) .aspx) и дескриптор, возвращаемый ['std :: thread :: native_handle()'] (http://en.cppreference.com/w/cpp/thread/thread/native_handle) может быть самым близким к вам. (Но я согласен с тем, что это невозможно сделать в рамках стандарта C++ 11, то есть без вызовов, специфичных для конкретной платформы.) – jogojapan

+7

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

ответ

3

Как указано в других комментариях, вы не можете создать поток «на конкретном ядре», так как C++ не знает таких архитектурных деталей. Более того, в большинстве случаев операционная система сможет достаточно хорошо управлять распределением потоков между ядрами/процессорами.

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

Если вы хотите спуститься по этой дороге, вам нужно будет изучить подпрограммы платформы. Например, для GNU/Linux с POSIX нитей вы хотите pthread_setaffinity_np(), в FreeBSD cpuset_setaffinity(), в Windows, SetThreadAffinityMask() и т.д.

у меня есть некоторые важные фрагменты кода здесь, если вы заинтересованы:

http://gitorious.org/piranhapp0x/mainline/blobs/master/src/thread_management.cpp

+0

@Atul, Сообщите нам, действительно ли вы получаете повышение производительности, просто позволяя ОС выполнять выделение для себя. – bazza

2

Я вполне уверен, что сродство ядра не включено в std :: thread. Предполагается, что ОС прекрасно способна наилучшим образом использовать имеющиеся ядра. Во всех, кроме самых экстремальных случаях, вы не собираетесь бить решение ОС, поэтому предположение справедливо.

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

Именно поэтому существуют пулы потоков. По умолчанию они имеют столько потоков, сколько есть ядер, автоматически настраиваемых языковой средой выполнения. AFAIK C++ 11 не имеет одного из них. Таким образом, одна хорошая вещь, которую вы можете сделать, чтобы получить оптимальную производительность, - это выяснить, сколько ядер есть и ограничить количество потоков, которые у вас есть на этом номере. В противном случае, вероятно, лучше всего доверять ОС.

Замечание Иоахима Пилеборга стоит обратить внимание, если работа, выполняемая каждым потоком, не перевешивает накладные расходы ввода-вывода.

+0

Замечательно, если после заполнения вектора я запускаю loop_for_each loop для соединения потоков? – Atul

+0

@Atul: почти наверняка нет. действие, которое вы выполняете в function_object параллельного_for_each (или parallel_for), должно, в общем, не выполнять операции синхронизации с другими потоками. На самом деле, parallel_for и parallel_for_each обычно становятся довольно запутанными (выполняются намного хуже), если вы вообще создаете собственное создание потоков. –

+0

... вы можете, с другой стороны, рассмотреть возможность создания вектора объектов (содержащих пути к файлам, которые вам нужно обработать), а затем с помощью parallel_for_each над вектором. parallel_for_each _is_ тщательно разработан для использования пула потоков с оптимальным количеством потоков и тщательно продуманной оптимизации близости. –

0

As быстрый обзор нарезки резьбы в контексте отправки потоков на сердечники:

Большинство современных ОС используют потоки уровня ядра или гибридные.С потоком уровня ядра ОС «видит» все потоки в каждом процессе; в отличие от потоков пользовательского уровня, которые используются на Java, где ОС видит один процесс и не знает потоков. Теперь, поскольку при поточной загрузке уровня ядра ОС может распознавать отдельные потоки процесса и управляет их отправкой на заданное ядро, существует потенциал для истинного параллелизма, когда несколько потоков одного и того же процесса выполняются на разных ядрах. Вы, как программист, не будете контролировать это, но при использовании std::thread; ОС решает. При поточной обработке пользовательского уровня управление потоками выполняется на уровне пользователя, а Java - в библиотеке управляет «отправкой». В случае гибридной потоковой передачи используется потоковая передача ядра, где каждый поток ядра представляет собой набор потоков пользовательского уровня.

Смежные вопросы