Ich versuche Quicksort mit std::threads
zu parallelisieren, und ich bekomme einen Fehler, den ich nicht kenne, seit ich Multithreading gestartet habe . Der Fehler ist wahrscheinlich so einfach, ich hüpfe ständig darüber. Kann jemand bitte etwas Licht auf das Problem werfen. Hier ist der Code und der einzige Fehler, der angezeigt wird:<function-style-cast> Fehler: Konnte nicht von 'initializer list' zu 'std :: thread'
#define _CRT_SECURE_NO_WARNINGS
#include <iostream> //cout, endl
#include <cstdlib> //srand
#include <algorithm>//copy, random_shuffle
#include <iterator> //ostream_iterator
#include "ratio.h"
#include <vector>
#include <iostream>
#include <thread>
#include "quicksort.h"
#include "sort_small_arrays.h"
template< typename T>
unsigned partition(T* a, unsigned begin, unsigned end) {
unsigned i = begin, last = end - 1;
T pivot = a[last];
for (unsigned j = begin; j<last; ++j) {
if (a[j]<pivot) {
std::swap(a[j], a[i]);
++i;
}
}
std::swap(a[i], a[last]);
return i;
}
/* iterative */
#define STACK
#define xVECTOR
#define xPRIORITY_QUEUE
#include <utility> // std::pair
template <typename T>
using triple = typename std::pair< T*, std::pair<unsigned, unsigned>>;
template< typename T>
struct compare_triples {
bool operator() (triple<T> const& op1, triple<T> const& op2) const {
return op1.second.first > op2.second.first;
}
};
#ifdef STACK
#include <stack>
template< typename T>
using Container = std::stack< triple<T>>;
#define PUSH push
#define TOP top
#define POP pop
#endif
#ifdef VECTOR
#include <vector>
template< typename T>
using Container = std::vector< triple<T>>;
#define PUSH push_back
#define TOP back
#define POP pop_back
#endif
#ifdef PRIORITY_QUEUE
#include <queue>
template< typename T>
using Container = std::priority_queue< triple<T>, std::vector<triple<T>>, compare_triples<T> >;
#define PUSH push
#define TOP top
#define POP pop
#endif
//Thread quicksorts a single range of elements and decrements thread counter at the end
template< typename T>
void threadsort_iterative_aux(Container<T> & ranges, int ¤tThreads)
{
triple<T> r = ranges.TOP();
ranges.POP();
T* a = r.first;
unsigned b = r.second.first;
unsigned e = r.second.second;
//base case
if (e - b<6) {
switch (e - b) {
case 5: quicksort_base_5(a + b); break;
case 4: quicksort_base_4(a + b); break;
case 3: quicksort_base_3(a + b); break;
case 2: quicksort_base_2(a + b); break;
}
continue;
}
unsigned q = partition(a, b, e);
ranges.PUSH(std::make_pair(a, std::make_pair(b, q)));
ranges.PUSH(std::make_pair(a, std::make_pair(q + 1, e)));
--currentThreads;
}
template< typename T>
void quicksort(T* a, unsigned begin, unsigned end, int num_threads)
{
//Number of threads currently running other than the main thread
int currentThreads = 0;
//Ranges of elements to sort
Container<T> ranges;
ranges.PUSH(std::make_pair(a, std::make_pair(begin, end)));
//Dynamic vector of threads
std::vector<std::thread> threads;
//Loops till all threads are done AND nothing left to sort
while (!ranges.empty() || currentThreads != 0)
{
//Doesn't bother doing anything if the range is empty but other threads are still running
if (!ranges.empty())
{
//If we can make more threads, make a thread and give it the top range to sort
if (currentThreads < num_threads)
{
++currentThreads;
threads.push_back(std::thread(threadsort_iterative_aux, std::ref(ranges), std::ref(currentThreads)));
}
//Starts sorting itself if maximum number of threads are running
else
{
triple<T> r = ranges.TOP();
ranges.POP();
T* a = r.first;
unsigned b = r.second.first;
unsigned e = r.second.second;
//Optimized sorting of a range between 2 and 5 elements
if (e - b < 6) {
switch (e - b) {
case 5: quicksort_base_5(a + b); break;
case 4: quicksort_base_4(a + b); break;
case 3: quicksort_base_3(a + b); break;
case 2: quicksort_base_2(a + b); break;
}
continue;
}
unsigned q = partition(a, b, e);
ranges.PUSH(std::make_pair(a, std::make_pair(b, q)));
ranges.PUSH(std::make_pair(a, std::make_pair(q + 1, e)));
}
}
}
}
template< typename T>
bool check_is_sorted(T* a, unsigned size)
{
for (unsigned int i = 1; i<size; ++i) {
if (!(a[i - 1] <= a[i])) {
return false;
}
}
return true;
}
bool test_int(unsigned size, unsigned num_threads) {
int* a = new int[size];
for (unsigned i = 0; i<size; ++i) { a[i] = i; }
std::srand(static_cast<unsigned int>(std::time(NULL)));
std::random_shuffle(a, a + size);
quicksort(a, 0, size, num_threads);
bool retval = check_is_sorted(a, size);
delete[] a;
return retval;
}
void test0() {
if (test_int(200, 1)) { std::cout << "OK\n"; }
else { std::cout << "Failed\n"; }
}
#include <cstdio> /* sscanf */
int main(int argc, char ** argv)
{
test0();
return 0;
}
Severity Code Beschreibung Projektdateizeile Fehler C2440 ‚‘: kann nicht aus konvertieren ‚Initialisiererliste‘ auf ‚std :: thread‘ Linie 145 (enthält:
threads.push_back (std :: Gewinde (threadsort_iterative_aux, std :: ref (Bereiche), std :: ref (currentThreads)));)
Hmmm, ich dachte, Ihre Eingabe würde den Fehler beheben. Ich änderte die Zeile in folgende Zeile: threads.push_back (std :: thread (threadsort_iterative_aux, std :: ref (bereiche), std :: ref (currentThreads))); Aber der gleiche Fehler bleibt bestehen. Habe ich es falsch gemacht? Oder haben Sie einen Fehler bemerkt, mit dem ich nach der Behebung des Fehlers umgehen musste? –
@AmrotheStudent Diese Zeile sieht jetzt korrekt aus. Leider ist der von Ihnen gepostete Code unvollständig, was es schwierig macht, den Fehler weiter zu diagnostizieren. Können Sie den Beitrag bearbeiten, um [ein vollständiges, in sich abgeschlossenes Beispiel] (http://stackoverflow.com/help/mcve) anzuzeigen und die vollständige Fehlermeldung, die Sie vom Compiler erhalten, einzubeziehen? – ComicSansMS
Nun, ich bin nicht sicher, wie viel ich dir zeigen soll, also habe ich rausgenommen, was ich für irrelevant hielt. Ich habe die Treiber und Hauptfunktion verlassen, Sie sollten in der Lage sein, kopieren und einfügen und laufen, um den gleichen Fehler jetzt zu sehen. Ich werde den Code wieder bearbeiten, wenn es noch zu viel ist. –