2013-04-04 3 views
6

Ich benutze Visual Studio 2012. Ich habe ein Modul, wo ich eine riesige Menge von Dateien von der Festplatte nach dem Durchlaufen ihrer entsprechenden Pfade durch ein XML lesen müssen. Dazu iWie sicherzustellen, dass std :: thread in Multi-Core erstellt werden?

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

In einer while-Schleife mache ich schiebe einen neuen Thread in diesen Vektor zurück, so etwas wie

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

Mein C++ 11 Multi-Threading Wissen ist limited.The Frage, die Ich habe hier, ist, wie erstellt man einen Thread auf einem bestimmten Kern? Ich weiß von parallel_for und parallel_for_each in vs2012, die die Kerne optimal nutzen. Aber gibt es eine Möglichkeit, dies mit Standard C++ 11 zu tun?

+0

Die C++ - Thread-Funktionen haben keine Kenntnis von "Kernen" und daher können Sie einen Thread nicht an einen bestimmten Kern binden. –

+0

Ich weiß es nicht wirklich, aber ich vermute ['SetThreadAffinityMask'] (http://msdn.microsoft.com/en-us/library/ms686247 (v = vs.85) .aspx) und das Handle von zurückgegeben ['std :: thread :: native_handle()'] (http://en.cppreference.com/w/cpp/thread/thread/native_handle) ist möglicherweise am ehesten verfügbar. (Aber ich stimme zu, dass es keine Möglichkeit gibt, dies rein im C++ 11 Standard zu tun, dh ohne plattformspezifische Aufrufe.) – jogojapan

+7

Und als allgemeiner Hinweis, wenn Sie mehrere Threads verwenden, um aus mehreren Dateien auf demselben Dateisystem zu lesen Wahrscheinlich werden Sie das Programm _slower_ machen, da das Betriebssystem jedes Mal, wenn ein Threadkontextwechsel stattfindet, hin und her suchen muss. (Zumindest bei alten mechanischen Festplatten sollten moderne SSDs besser damit umgehen.) –

Antwort

3

Wie in anderen Kommentaren erwähnt, können Sie keinen Thread "auf einem bestimmten Kern" erstellen, da C++ keine Kenntnis von solchen architektonischen Details hat. Darüber hinaus wird das Betriebssystem in der Mehrzahl der Fälle in der Lage sein, die Verteilung von Threads zwischen Kernen/Prozessoren gut zu verwalten.

Es gibt Fälle, in denen das Erzwingen einer bestimmten Verteilung von Threads zwischen Kernen für die Leistung von Vorteil sein kann. Zum Beispiel könnte es durch Erzwingen eines Threads, auf einen bestimmten Kern ausgeführt zu werden, möglich sein, die Datenverschiebung zwischen verschiedenen Prozessor-Caches zu minimieren (was für die Leistung in bestimmten speichergebundenen Szenarien entscheidend sein kann).

Wenn Sie diesen Weg gehen wollen, müssen Sie plattformspezifische Routinen untersuchen. ZB für GNU/Linux mit POSIX-Threads finden Sie pthread_setaffinity_np(), in FreeBSD cpuset_setaffinity(), in Windows SetThreadAffinityMask() usw. wollen

Ich habe einige relevante Code-Schnipsel hier, wenn Sie interessiert sind:

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

+0

@Atul, Lassen Sie uns wissen, ob Sie tatsächlich eine Leistungsverbesserung erhalten, anstatt das Betriebssystem die Zuweisung für sich selbst durchführen zu lassen. – bazza

2

Ich bin ziemlich sicher, dass Core-Affinität nicht in Std :: Thread enthalten ist. Die Annahme ist, dass das Betriebssystem die verfügbaren Kerne optimal nutzen kann. In allen außer den extremsten Fällen, in denen Sie die Entscheidung des Betriebssystems nicht zu Fall bringen wollen, ist die Annahme fair.

Wenn Sie diese Route herunterfahren, müssen Sie Ihrem Code einige Entscheidungsfindungen hinzufügen, um die Maschinenarchitektur zu berücksichtigen und sicherzustellen, dass Ihre Entscheidung besser ist als die Betriebssysteme auf jedem Computer, auf dem Sie ausgeführt werden. Das kostet viel Mühe! Für Anfänger möchten Sie die Anzahl der Threads begrenzen, um die Anzahl der Kerne auf dem Computer zu entsprechen. Und Sie wissen nicht, was sonst in der Maschine passiert; das OS tut!

Deshalb gibt es Thread-Pools. Sie haben standardmäßig so viele Threads wie Kerne, die von der Sprachlaufzeit automatisch eingerichtet werden. AFAIK C++ 11 hat keinen von denen. Sie können also die optimale Leistung erzielen, indem Sie herausfinden, wie viele Kerne vorhanden sind, und die Anzahl der Threads auf diese Anzahl begrenzen. Ansonsten ist es wahrscheinlich am besten, dem Betriebssystem zu vertrauen.

Joachim Pileborgs Kommentar ist es wert, beachtet zu werden, es sei denn, die von jedem Thread geleistete Arbeit überwiegt den I/O-Overhead.

+0

Ist es in Ordnung, wenn ich nach dem Auffüllen des Vektors parallel_for_each Schleife laufen, um die Threads beizutreten? – Atul

+0

@Atul: fast sicher nicht. Die Aktion, die Sie im function_object von parallel_for_each (oder parallel_for) ausführen, sollte im Allgemeinen keine Synchronisationsoperationen mit anderen Threads durchführen. In der Tat, parallel_for und parallel_for_each werden in der Regel ziemlich verwirrt (führen viel schlechter), wenn Sie überhaupt eine eigene Thread-Erstellung machen. –

+0

... können Sie auch einen Vektor von Objekten erstellen (der die zu bearbeitenden Dateipfade enthält) und dann parallel_for_each über den Vektor verwenden. parallel_for_each _is_ ist sorgfältig darauf ausgelegt, einen Threadpool mit einer optimalen Anzahl von Threads und sorgfältig entworfenen Affinitätsoptimierungen zu verwenden. –

0

Wie Ein schneller Überblick über das Threading im Zusammenhang mit dem Versenden von Threads an Kerne:

Die meisten modernen Betriebssysteme verwenden Kernel-Threads oder Hybrid.Mit Kernel-Threading "sieht" das Betriebssystem alle Threads in jedem Prozess; im Gegensatz zu Threads auf Benutzerebene, die in Java verwendet werden, wo das Betriebssystem einen einzelnen Prozess sieht und keine Kenntnisse über Threads besitzt. Da das Betriebssystem die einzelnen Threads eines Prozesses erkennen kann und deren Verteilung auf einen bestimmten Kern verwaltet, besteht das Potenzial für echte Parallelität, bei der mehrere Threads desselben Prozesses auf verschiedenen Kernen ausgeführt werden. Sie als Programmierer haben jedoch keine Kontrolle darüber, wenn Sie std::thread verwenden; Das Betriebssystem entscheidet. Mit Threading auf Benutzerebene wird die gesamte Verwaltung von Threads auf Benutzerebene durchgeführt, mit Java verwaltet eine Bibliothek den "Versand". Im Fall von Hybrid-Threading wird Kernel-Threading verwendet, wobei jeder Kernel-Thread tatsächlich ein Satz von Threads auf Benutzerebene ist.

Verwandte Themen