Domanda

MODIFICARE: Posso eseguire lo stesso programma due volte contemporaneamente senza alcun problema: come posso duplicarlo con OpenMP o con qualche altro metodo?

Questo è il quadro fondamentale del problema.

//Defined elsewhere
class SomeClass
{
public:
  void Function()
  {
    // Allocate some memory
    float *Data;
    Data = new float[1024];

    // Declare a struct which will be used by functions defined in the DLL
    SomeStruct Obj;
    Obj = MemAllocFunctionInDLL(Obj);

    // Call it
    FunctionDefinedInDLL(Data,Obj);

    // Clean up
    MemDeallocFunctionInDLL(Obj);
    delete [] Data;        
  }
}

void Bar()
{
   #pragma omp parallel for
   for(int j = 0;j<10;++j)
   {
     SomeClass X;
     X.Function();
   }
}

Ho verificato che quando si tenta di deallocare parte della memoria MemDeallocFunctionInDLL(), IL _CrtIsValidHeapPointer() l'asserzione fallisce.

È perché entrambi i thread stanno scrivendo sulla stessa memoria?

Quindi, per risolvere questo problema, ho pensato di fare SomeClass privato (questo mi è totalmente estraneo, quindi ogni aiuto è apprezzato).

void Bar()
{
   SomeClass X;
   #pragma omp parallel for default(shared) private(X)
   for(int j = 0;j<10;++j)
   {         
     X.Function();
   }
}

E Ora fallisce quando ci prova allocare memoria all'inizio per Data.

Nota: Posso apportare modifiche alla DLL, se necessario

Nota: Funziona perfettamente senza #pragma omp parallel for

MODIFICARE: Ora Bar Somiglia a questo:

void Bar()
{
   int j
   #pragma omp parallel for default(none) private(j)
   for(j = 0;j<10;++j)
   {
     SomeClass X;         
     X.Function();
   }
}

Ancora nessuna fortuna.

È stato utile?

Soluzione

Scopri MemAllocFunctionInDLL, FunctionDefinedInDLL, MemDeallocFunctionInDLL sono thread-safe, O rientrante.In altre parole, queste funzioni sono variabili statiche o variabili condivise?In tal caso, è necessario assicurarsi che queste variabili non siano danneggiate da altri thread.

Il fatto che senza omp-for vada bene potrebbe significare che non hai scritto correttamente alcune funzioni per essere thread-safe.

Mi piacerebbe vedere che tipo di allocazione di memoria/funzioni libere è stata utilizzata in Mem(Alloc|Dealloc)FunctionInDLL.

Aggiunto:Sono abbastanza sicuro che le tue funzioni in DLL non siano thread-safe.È possibile eseguire questo programma contemporaneamente senza problemi.Sì, dovrebbe andare bene a meno che il tuo programma non utilizzi risorse condivise a livello di sistema (come memoria globale o memoria condivisa tra processi), il che è molto raro.In questo caso, nessuna variabile condivisa nei thread, quindi il tuo programma funziona correttamente.

Ma, invocando queste funzioni in multithread (ciò significa in un singolo processo) blocca il tuo programma.Significa che ci sono alcune variabili condivise tra i thread e potrebbe essere stato danneggiato.

Non è un problema di OpenMP, ma solo un bug del multithreading.Potrebbe essere semplice risolvere questo problema.Si prega di dare un'occhiata alle funzioni DLL per verificare se sono sicure per essere chiamate contemporaneamente da molti thread.

Come privatizzare le variabili statiche

Diciamo che abbiamo tali variabili globali:

static int  g_data;
static int* g_vector = new int[100];

La privatizzazione non è altro che un creare privato copia per ogni thread.

int  g_data[num_threads];
int* g_vector[num_threads];
for (int i = 0; i < num_threads; ++i)
  g_vector[i] = new int[100];

E quindi qualsiasi riferimento a tali variabili lo è

// Thread: tid
g_data[tid] = ...
.. = g_vector[tid][..]

Sì, è piuttosto semplice.Tuttavia, questo tipo di codice potrebbe avere un file falsa condivisione problema.Ma la falsa condivisione è una questione di prestazioni, non di correttezza.

Innanzitutto, prova a privatizzare qualsiasi variabile statica e globale.Quindi, verificane la correttezza.Successivamente, vedi l'accelerazione che otterresti.Se l'aumento di velocità è scalabile (diciamo 3,7 volte più veloce su quad core), allora va bene.Ma, in caso di bassa velocità (come l'accelerazione 2x su quad core), probabilmente guardi al problema della falsa condivisione.Per risolvere il problema della falsa condivisione, tutto ciò che devi fare è semplicemente inserire un po' di imbottitura nelle strutture dati.

Altri suggerimenti

Al posto di

delete Data

è necessario scrivere

delete [] Data;

Ovunque tu nuovo [], assicurarsi di utilizzare delete [].

Sembra che il problema non è specifico per OpenMP. Hai provato a eseguire l'applicazione senza includere #pragma parallelo?

default (condivisa) significa che tutte le variabili sono condivise tra i thread, che non è quello che si desidera. Cambiamento che per impostazione predefinita (nessuno).

privato (X) farà una copia di X per ogni thread, però, nessuno di loro verrà inizializzata in modo che qualsiasi costruzione non sarà necessariamente essere eseguita.

Credo che sarebbe meglio con il vostro approccio iniziale, mettere un punto di interruzione nella chiamata Dealloc, e vedere ciò che il puntatore di memoria è e ciò che contiene. È possibile vedere i href="http://en.wikipedia.org/wiki/Magic_number_%28programming%29" per dire se la memoria è stata sovrascritta al end di una singola chiamata, o dopo un thread.

Per inciso, io parto dal presupposto che questo funziona se si esegue una volta, senza l'anello di OMP?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top