2017-02-12 2 views
-2

Ich versuche, die Bibliothek von mir für einige geophysikalische Berechnungen zu aktualisieren. Ich habe das Beispiel für die Demonstration erstellt. Ich würde gerne mehrere Threads dazu verwenden. Nehmen wir an, ich möchte die Matrixelemente in meiner eigenen Struktur zusammenfassen. Die Summe wird Zeile für Zeile berechnet:So erhalten Sie einen einzelnen Wert aus mehreren Threads (Array-Summierung Zeile für Zeile) - C++

Hier einige Quellcode mit Kommentaren

HEADER:

#include <iostream> 

#include <cmath> 
#include <cstdlib> /* rand */ 
#include <thread> /* multithread library */ 
        /* std::thread::hardware_concurrency() from c++ : --stdc=c++11 */ 
#include <algorithm> 
#include <iomanip> 
#include <time.h> 

#define NUM_T  4 

STRUKTUR:

struct ARRAY { 
    /* Matrix with n-rows, m-cols */ 
    double** mtrx; 
    unsigned int rows; 
    unsigned int cols; 
}; 

erstellen und löschen:

ARRAY create_array (unsigned int r,unsigned int c){ 
    struct ARRAY mtrx; 
    double** elem; 

    elem = new double*[r]; 
    for (unsigned int i=0; i<r; i++){ 
     elem[i] = new double[c]; 
    }; 

    mtrx.mtrx = elem; 
    mtrx.rows = r; 
    mtrx.cols = c; 

    return mtrx; 
}; 

void delete_array (struct ARRAY& mtrx){ 
    for (unsigned int i = 0; i < mtrx.rows; ++i){ 
      delete mtrx.mtrx[i]; 
      mtrx.mtrx[i] = NULL; 
    }; 
    delete mtrx.mtrx; 
}; 

Füllen einige zufällige Werte:

void rand_array (struct ARRAY& mtrx){ 
    for (unsigned int i = 0; i < mtrx.rows; i++){ 
     for(unsigned int j = 0; j < mtrx.cols; j++){ 
      mtrx.mtrx[i][j] = rand() % 1000; /* rand number from 0-1000; */ 
     } 
    } 
}; 

Und hier ist das Hauptproblem (Ich bin mir bewusst, dass die Matrix mit zufälligen Werten füllen zu parallelisiert werden kann).

Sum (Dummy-Funktion)

inline double sum_array_line (double* arr_line, unsigned int ncols){ 
    double s = 0.0; 
    for (unsigned int i = 0; i < ncols; i++){ 
     s += arr_line[i]; 
    } 
    return s; 
}; 

Und am Ende der letzte up:

double sum_array_mt (struct ARRAY mtrx){ 
    thread t[NUM_T]; 

    double sum__ = 0.0; 

    unsigned int i = 0 ; 
    while (i < mtrx.rows){ 
     for (unsigned int j = 0; j < NUM_T; j++){ 
      t[j] = thread(sum_array_line, mtrx.mtrx[i++], mtrx.cols); 
     } 

     for (unsigned int j = 0 ; j < NUM_T; j++){ 
      t[j].join(); 
     } 
    } 
    return sum__; 
} 

Das Hauptproblem ist, ich habe keine Ahnung, wie der Wert aus einzelnen Thread erhalten passieren zu Summe__ . Kann mir bitte jemand einen Hinweis geben?

Und natürlich die Hauptfunktion:

int main(int argc, char* argv[]){ 

    ARRAY mat = create_array(100, 100); 
    rand_array(mat); 
    double sum_par = sum_array_mt(mat); 
    cout << "The sum of matrix is: " << sum_par << endl; 

    delete_array(mat); 

    return 0; 
} 

Vielen Dank, die Lösung für die Bereitstellung. Wenn es funktioniert, kann ich es leicht für meine Bibliothek ändern. Vielen Dank.

+0

Bitte beschreiben Sie die Frage/Problem bitte mit Ihrem Titel. –

+0

Dies behandelt die Frage nicht, aber Namen, die zwei aufeinanderfolgende Unterstriche ('sum__') enthalten, und Namen, die mit einem Unterstrich gefolgt von einem Großbuchstaben beginnen, sind für die Implementierung reserviert. Benutze sie nicht in deinem Code. –

+0

Es gibt ein paar andere Probleme hier neben nur die Threads zum Arbeiten zu bekommen.Was ist, wenn die Dimensionen der Matrix nicht durch NUM_T teilbar sind? Versuchen Sie zum Beispiel einen 10x10 Testfall. Den Benutzer dazu zu zwingen, etwas manuell zu löschen, ist nicht wirklich gut C++ - Übung, das ist eine C-Sache. Sie sollten normalerweise einen Destruktor für diesen Zweck bereitstellen. Verwenden Sie auch std :: vector oder std :: array und machen Sie einige Benchmarks, sie sind viel sicherer (und einfacher) als neu/Löschen einer Reihe von regulären Arrays. –

Antwort

0

Es gibt keine direkte Möglichkeit, den Rückgabewert einer Funktion zu erhalten, die in einem Thread ausgeführt wird. Übergeben Sie stattdessen einen Verweis an die Stelle, an der Sie das Ergebnis speichern möchten. Das bedeutet sum_array_line Ändern eine Referenz zu nehmen:

void sum_array_line (double* arr_line, unsigned int ncols, 
    std::reference_wrapper<double> res){ 
    double s = 0.0; 
    for (unsigned int i = 0; i < ncols; i++){ 
     s += arr_line[i]; 
    } 
    res = s; 
}; 

und das Ändern Ihre innere Schleife die Variable für das Ergebnis zu übergeben:

double results[NUM_T]; 
for (unsigned j = 0; j < NUM_T; ++j) { 
    t[j] = thread(sum_array_line, mtrx.mtrx[i], mtrx.cols, std::ref(results[j])); 
    ++i; 
} 

und, wie Sie jeden Faden verbinden, fügen Sie das Ergebnis auf den Lauf Gesamt:

+1

Benötigen Sie nicht std :: ref, wenn Sie auf einen Thread verweisen? –

+0

@BillHarper - yup. Danke, behoben. –

+0

Vielen Dank für die Bereitstellung neuer Lösung, aber auf diese Weise liefert jedes Ergebnis von resutls [j] einen Wert wie "3.114606e-317". – Buddy

0

Wenn ich upgrade der Funktionen, die ich verwende, um die Summierung mit 4 Threads zu tun. Für die Matrix 20 000 × 20 000 beträgt die Zeit, die benötigt wird, um die Summe zu berechnen, 0,6 Sekunden für einzelne Thread-Zugriffselemente nacheinander (2 für Zyklen) und 1,0 Sekunden für die parallele Berechnung mit 4 Threads. Ich verstehe nicht. Sollte die Multithread-Lösung nicht schneller sein?

Verwandte Themen