2017-06-02 3 views
0

Ich habe versucht, einen Code zu parallelisieren, aber es verschlechterte nur die Leistung. Ich schrieb einen Fortran-Code, der mehrere Monte-Carlo-Integrationen ausführt und dann ihren Mittelwert findet.Leistungsproblem während der Parallelisierung mit OpenMP

 implicit none 
     integer, parameter :: n=100 
     integer, parameter :: m=1000000 
     real, parameter :: pi=3.141592654 

     real MC,integ,x,y 
     integer tid,OMP_GET_THREAD_NUM,i,j,init,inside 
     read*,init 
     call OMP_SET_NUM_THREADS(init) 
     call random_seed() 
!$OMP PARALLEL DO PRIVATE(J,X,Y,INSIDE,MC) 
!$OMP& REDUCTION(+:INTEG) 
     do i=1,n 
     inside=0 
     do j=1,m 
      call random_number(x) 
      call random_number(y) 

      x=x*pi 
      y=y*2.0 

      if(y.le.x*sin(x))then 
      inside=inside+1 
      endif 

     enddo 

     MC=inside*2*pi/m 
     integ=integ+MC/n 
     enddo 
!$OMP END PARALLEL DO 

     print*, integ 
     end 

Wie ich die Anzahl der Threads erhöhen, Laufzeit erhöht sich drastisch. Ich habe nach Lösungen für solche Probleme gesucht und in den meisten Fällen sind geteilte Speicherelemente das Problem, aber ich kann nicht sehen, wie es meinen Fall beeinflusst.

Ich verwende es auf einem 16-Core-Prozessor mit Intel Fortran-Compiler.

EDIT: Das Programm nach dem Hinzufügen implicit none, alle Variablen deklarieren und das Hinzufügen der privaten Klausel

+1

Willkommen. Bitte nimm die [Tour], sie wird allen Neulingen empfohlen. Wie hast du die Zeit gemessen? –

+0

Bitte sehen Sie, wie ich die Einrückung in Ihrem Code geändert habe. Es ist gut, all Ihren Code eingerückt einzureichen, damit die Leute die Struktur sehen können. Es ist gut für Sie, Ihre Quelldateien auch so zu behalten. –

+0

Was ist "innen"? Woher kommt das? Bitte stellen Sie sicher, dass Sie 'IMPLICIT NONE' verwenden. –

Antwort

0

Sie nicht RANDOM_NUMBER für High Performance Computing und definitiv nicht in parallelen Threads verwenden sollten. Es gibt KEINE Garantien über die Qualität des Zufallsgenerators und über die Threadsicherheit des Standard-Zufallsgenerators. Siehe Can Random Number Generator of Fortran 90 be trusted for Monte Carlo Integration?

Einige Compiler verwenden einen schnellen Algorithmus, der nicht parallel aufgerufen werden kann. Einige Compiler haben eine langsame Methode, können aber von parallel aufgerufen werden. Einige werden sowohl schnell als auch parallel sein. Einige werden zufällige Sequenzen schlechter Qualität erzeugen, manche besser.

Sie sollten eine parallele PRNG-Bibliothek verwenden. Da sind viele. Sehen Sie hier für Empfehlungen für Intel https://software.intel.com/en-us/forums/intel-math-kernel-library/topic/283349 Ich benutze Bibliothek basierend auf http://www.cmiss.org/openCMISS/wiki/RandomNumberGenerationWithOpenMP in meiner eigenen leicht verbesserte Version https://bitbucket.org/LadaF/elmm/src/e732cb9bee3352877d09ae7f6b6722157a819f2c/src/simplevtk.f90?at=master&fileviewer=file-view-default aber sei vorsichtig, mir ist nicht die Qualität der Reihenfolge in meinen Anwendungen, nur über die Geschwindigkeit.


Zur alten Version:

Sie haben ein Rennen dort Zustand.

Mit

inside=inside+1 

mehr Threads können zum Schreiben konkurrieren und die Variable zu lesen. Sie müssen den Zugriff irgendwie synchronisieren. Wenn Sie es machen reduction werden Sie Probleme haben mit

integ=integ+MC/n 

, wenn Sie es privat machen, dann inside=inside+1 nur lokal zählen.

MC scheint auch in einem Race-Zustand zu sein, weil mehr Threads darin schreiben werden. Es ist überhaupt nicht klar, was MC tut und warum es dort ist, weil Sie den Wert nirgendwo verwenden. Sind Sie sicher, dass der angezeigte Code vollständig ist? Wenn nicht, sehen Sie bitte unter Minimal, Complete, and Verifiable example nach.

Sehen Sie diese With OpenMP parallelized nested loops run slow viele andere Beispiele, wie eine Race-Bedingung Programm verlangsamen kann.

+0

' innen' gespeichert ist. sei eine private Variable. Ich wünsche, dass die äußere Schleife parallel ausgeführt wird, so dass die innere Schleife unabhängig in verschiedenen Fäden läuft. 'MC' speichert den Wert der Integration. "MC" wird n-mal unabhängig berechnet und der Mittelwert wird in "integ" gespeichert. Ich habe auch versucht, "integ" zu entfernen, so dass alles privat ist, nur um den Zeitunterschied zu sehen, aber es hatte keinen Einfluss auf die Laufzeit. –

+0

Warum denken Sie, dass es sich um einen privaten Standard handelt? Sie haben keine solche Einstellung in Ihrem Code. Standardmäßig ist alles geteilt. Ich bin der festen Überzeugung, dass das Programm wegen der Race-Bedingung langsam ist. Haben Sie die Ergebnisse des seriellen und parallelen Codes verglichen? Sind sie gleich oder unterscheiden sie sich? Ich wette, sie werden sich unterscheiden. –

+0

Ich habe versucht, 'DEFAULT (PRIVATE)' hinzuzufügen, aber es hatte keine Wirkung (deshalb dachte ich, dass es standardmäßig privat sein muss, mein Schlechter). Überraschenderweise sind die Ergebnisse für den seriellen und parallelen Code mit oder ohne Verwendung von DEFAULT (PRIVATE) gleich. Auch das Ergebnis ist bis zu 3 Dezimalstellen korrekt. Ich habe auch versucht, alle Variablen mit der 'PRIVATE'-Klausel zu definieren, aber das hat auch nicht geholfen. –

Verwandte Themen