2009-09-07 27 views
9

Sto sperimentando con OpenCL per aumentare la velocità del nostro software. Lavoriamo molto con le mappe e, per semplificare, rappresentiamo una mappa come std :: vector < std :: vector>. L'API OpenCL utilizza come argomento argomenti puntatori c-style grezzi, ad esempio int * nel caso precedente.std :: vettori stile c e stile

Le mie domande:

  • ci sono garanzie di attuazione nel STL che vettore è, internamente, consecutiva in memoria?
  • Posso trasmettere in modo sicuro uno std :: vector a int * e mi aspetto che funzioni?
  • Nel caso di un vettore di vettori, posso ancora supporre che ciò sia vero? Mi aspetto che il vettore possa contenere altri dati di stato, o problemi di allineamento, o forse qualcos'altro ...
  • Qual è il modo migliore per avvicinarsi a questo? Scrivi una struttura dati 2D personalizzata che contenga un buffer interno contiguo e che lavori con quello? Dovrei copiare molto da/per i vettori ...

Grazie.

+0

Questa domanda potrebbe anche interessare: http://stackoverflow.com/questions/1339470/how-to-get-the-address-of-the-stdvector-buffer-start-most-elegantly –

+1

Nota che 'vector ' è un'eccezione alla regola http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=98 – Motti

risposta

17

Esistono garanzie di implementazione in stl che il vettore è, internamente, consecutivo in memoria?

A partire dal C++ 03, sì, un vettore è garantito per utilizzare l'archiviazione contiguo. (In C++ 98, c'era una scappatoia accidentale quindi un'implementazione potrebbe utilizzare ipoteticamente storage non contiguo, ma è stata risolta nella revisione del 2003 dello standard - e nessuna implementazione in realtà utilizza lo storage non contiguo perché esso ' d essere una pessima idea)

Posso trasmettere in modo sicuro uno std :: vector a int * e mi aspetto che funzioni?

Il modo normale è &v[0].(&*v.begin() probabilmente funzionerebbe anche io, ma mi sembra di ricordare che ci sia un testo birichino nello standard che rende questo non affidabile al 100%)

No. Perché ti aspetti che funzioni? Un vettore è una classe. Non è un puntatore. Solo contiene un puntatore.

Nel caso di un vettore di vettori, posso ancora ritenere che ciò sia vero? Mi aspetto che il vettore possa contenere altri dati di stato, o problemi di allineamento, o forse qualcos'altro ...

Il vettore si comporta allo stesso modo qualunque cosa si memorizzi in esso. Se si crea un vettore di vettori, si finisce con un oggetto che contiene un puntatore a un array assegnato all'heap, in cui ogni elemento è un oggetto che contiene un puntatore a un array allocato all'heap.

Per quanto riguarda l'approccio da seguire, dipende da molti fattori. Quanto è grande il set di dati totale? Potresti voler assegnare l'intera tabella in modo contiguo. Con un vettore di vettori, ogni riga è un'allocazione separata.

+0

Grazie. In effetti ho espresso male la mia domanda, intendevo "lanciare il primo elemento al puntatore" piuttosto che "lanciare il vettore stesso" o "l'indirizzo del vettore stesso".Ad ogni modo sembra che non ci sia modo di lavorare facilmente con i contenuti grezzi di un vettore di vettori, dovrò ripensare il modo in cui lavoro con i dati. Le dimensioni tipiche sono tra 500x500xsizeof (char unsigned) e 2500x2500xsizeof (double), quindi tra 20 e 50 di quelle, quindi abbastanza grandi. – Roel

+0

Boost.MultiArray farebbe bene il lavoro per te. In alternativa, lo allocerei come singolo array o vettore contiguo abbastanza grande da contenere l'intera tabella 2d – jalf

+1

Nota che 'vector ' è l'eccezione al caso che '& v [0]' assegni a una matrice di stile 'C' . – Motti

3

Esistono garanzie di attuazione nel stl che vettore è, internamente, consecutiva in memoria?

Anche se non posso citare gli standard qui, ho visto il codice in librerie di alta qualità assumendo questo layout (vale a dire, POCO).

Posso trasmettere in modo sicuro uno std :: vector a int * e mi aspetto che funzioni?

In particolare, non è possibile rielaborare il vettore stesso. Ma, ho visto il seguente codice:

std::vector<int> vec; 
int* ptr = &vec[0]; 

Nel caso di un vettore di vettori, posso comunque assumere questo è vero? Mi aspetto che il vettore possa contenere altri dati di stato, o problemi di allineamento, o forse qualcos'altro ...

Probabilmente non si può trasmettere un vettore di vettori a un array lineare. Ogni vettore riserva il proprio intervallo di memoria e non è possibile aspettarsi che tutti questi intervalli siano sequenziali.

+1

non è possibile trasmettere un iteratore a un puntatore – jalf

+0

@jalf: Grazie, si ' Hai ragione. Ho confuso e vec [0] con (int *) vec.begin(). –

4
  • Esistono garanzie di attuazione nel stl che vettore è,
    internamente, consecutivi in ​​memoria

Sì, è un array dinamico. Lo standard garantisce che gli oggetti all'interno del vettore siano memorizzati consecutivamente.

  • Posso lanciare in modo sicuro uno std :: vector a int * e si aspettano che al lavoro?

No, ma è possibile utilizzare begin() e utilizzarlo come il puntatore.

  • Esistono garanzie di attuazione nel stl che vettore è,
    internamente, consecutivi in ​​memoria

No, poiché vettore può contenere alcune variabili membro interno l'intero array 2D no essere memoria continua posizione

+1

"No, ma puoi usare begin() e usarlo come puntatore.", Che non è generalmente vero, e sicuramente non garantito dallo standard. Dovresti sempre prendere l'indirizzo dell'iteratore dereferenziato per ottenere un puntatore, quindi "& * v.begin()" i.s.o. solo "v.begin()" – Pieter

2

Hai menzionato in un commento che si lavora con dati fino a 2500x2500xsizeof (doppi). In tal caso, suggerirei di utilizzare un singolo vettore anziché il vettore di vettori. Assegna gli elementi NxM in un vettore e avvolgili in una classe che espone l'indicizzazione bidimensionale, se lo desideri. Ottieni tutti i vantaggi del vettore con un sovraccarico minimo e tutti i tuoi dati sono ancora nella memoria contigua per un'elaborazione veloce.

+0

Sì, questo è probabilmente l'approccio che dovremmo prendere, almeno nel contesto di questa domanda. Il problema è che anche i nostri tipi di dati "mappa" devono essere in grado di leggere da posizioni diverse (su una rete, dal disco per mappe troppo grandi per adattarsi alla memoria (le mappe da 20 gigabyte non fanno eccezione), ... Dovremo semplicemente testare alcuni approcci, o implementarne diversi e disporre di un meccanismo di selezione run-time che determina il comportamento ottimale sulla macchina/set di problemi dell'utente, comunque grazie per il tuo commento. – Roel