Che cos'è la "vettorializzazione"?


190

Diverse volte, ho incontrato questo termine in matlab, fortran ... qualche altro ... ma non ho mai trovato una spiegazione che cosa significhi e cosa significhi? Quindi sto chiedendo qui, che cos'è la vettorializzazione e cosa significa, ad esempio, che "un ciclo è vettorializzato"?


1
@geoffspear Il link sembra essere stato spostato in en.wikipedia.org/wiki/Array_programming
Mi piace scrivere il codice

Risposte:


225

Molte CPU dispongono di set di istruzioni "vettoriali" o "SIMD" che applicano la stessa operazione simultaneamente a due, quattro o più parti di dati. I moderni chip x86 hanno le istruzioni SSE, molti chip PPC hanno le istruzioni "Altivec" e persino alcuni chip ARM hanno un set di istruzioni vettoriali, chiamato NEON.

"Vectorization" (semplificato) è il processo di riscrittura di un ciclo in modo che invece di elaborare un singolo elemento di un array N volte, elabori (diciamo) 4 elementi dell'array contemporaneamente N / 4 volte.

(Ho scelto 4 perché è quello che l'hardware moderno è più probabilmente in grado di supportare direttamente; il termine "vettorializzazione" è anche usato per descrivere una trasformazione del software di livello superiore in cui potresti semplicemente sottrarre del tutto il ciclo e descrivere semplicemente il funzionamento su array invece degli elementi che li compongono)


La differenza tra vettorializzazione e srotolamento del ciclo: considerare il seguente ciclo molto semplice che aggiunge gli elementi di due array e memorizza i risultati in un terzo array.

for (int i=0; i<16; ++i)
    C[i] = A[i] + B[i];

Srotolare questo ciclo lo trasformerebbe in qualcosa del genere:

for (int i=0; i<16; i+=4) {
    C[i]   = A[i]   + B[i];
    C[i+1] = A[i+1] + B[i+1];
    C[i+2] = A[i+2] + B[i+2];
    C[i+3] = A[i+3] + B[i+3];
}

La vettorializzazione, d'altra parte, produce qualcosa del genere:

for (int i=0; i<16; i+=4)
    addFourThingsAtOnceAndStoreResult(&C[i], &A[i], &B[i]);

Dove "addFourThingsAtOnceAndStoreResult" è un segnaposto per qualsiasi intrinseco / i utilizzato / i dal compilatore per specificare le istruzioni vettoriali. Si noti che alcuni compilatori sono in grado di vettorializzare automaticamente loop molto semplici come questo, che spesso possono essere abilitati tramite un'opzione di compilazione. Algoritmi più complessi richiedono ancora l'aiuto del programmatore per generare un buon codice vettoriale.


11
Qual è la differenza tra questo e loop svolgendo / svolgendo?
Jeremy Powell,

1
Non è vero che un compilatore avrebbe un lavoro più semplice che vettorializza automaticamente il ciclo srotolato?
Nikos Athanasiou,

@NikosAthanasiou: è plausibile, ma in generale un compilatore dovrebbe essere in grado di autovectorizzare entrambi i loop, poiché sono entrambi abbastanza semplici.
Stephen Canon,

1
@StephenCanon come si può verificare se alcune linee sono state vettorializzate o no? Se uno usasse objdump, cosa cercherebbe nell'output di objdump?
user1823664

3
@ Shuklaswag: la vettorializzazione è qualcosa che i compilatori possono fare per te, ma è anche qualcosa che i programmatori fanno esplicitamente da soli. Il sistema operativo non è coinvolto.
Stephen Canon,

32

Vettorizzazione è il termine per convertire un programma scalare in un programma vettoriale. I programmi vettorizzati possono eseguire più operazioni da una singola istruzione, mentre lo scalare può operare solo su coppie di operandi contemporaneamente.

Da Wikipedia :

Approccio scalare:

for (i = 0; i < 1024; i++)
{
   C[i] = A[i]*B[i];
}

Approccio vettorializzato:

for (i = 0; i < 1024; i+=4)
{
   C[i:i+3] = A[i:i+3]*B[i:i+3];
}

non è essenzialmente uguale all'approccio scalare? La tua sintassi e l'avanzamento del loop sono diversi, ma sotto lo stai ancora moltiplicando 4 volte. Ma in qualche modo sarà più veloce probabilmente la CPU ha istruzioni che fanno qualche trucco chiamato Vectorization.
mskw,

Sembra che risponderò alla mia domanda qui. La sintassi nell'approccio di vettorializzazione quando il complier lo vede, lo tradurrà in istruzioni CPU ottimizzate che moltiplicano i vettori. Come SIMD.
mskw,

10

Si riferisce alla capacità di eseguire singole operazioni matematiche su un elenco - o "vettore" - di numeri in un unico passaggio. Lo vedi spesso con Fortran perché è associato al calcolo scientifico, che è associato al supercalcolo, dove è apparsa per la prima volta l'aritmetica vettoriale. Oggi quasi tutte le CPU desktop offrono una qualche forma di aritmetica vettoriale, attraverso tecnologie come SSE di Intel. Le GPU offrono anche una forma di aritmetica vettoriale.


7

La vettorializzazione è ampiamente utilizzata nell'informatica scientifica in cui enormi blocchi di dati devono essere elaborati in modo efficiente.

In una vera applicazione di programmazione, so che è usato in NUMPY (non sono sicuro di altro).

Numpy (pacchetto per il calcolo scientifico in Python), utilizza la vettorializzazione per una rapida manipolazione dell'array n-dimensionale, che generalmente è più lento se fatto con opzioni di Python integrate per la gestione di array.

anche se ci sono tonnellate di spiegazioni là fuori, QUI È QUALE DEFINIZIONE DI VETTORIZZAZIONE COME IN NUMEROSA PAGINA DI DOCUMENTAZIONE

La vettorializzazione descrive l'assenza di qualsiasi ciclo esplicito, indicizzazione, ecc. Nel codice - queste cose stanno avvenendo, ovviamente, proprio "dietro le quinte" in un codice C ottimizzato e precompilato. Il codice vettoriale ha molti vantaggi, tra cui:

  1. il codice vettoriale è più conciso e più facile da leggere

  2. meno righe di codice generalmente significano meno bug

  3. il codice assomiglia più da vicino alla notazione matematica standard (rendendo più semplice, in genere, codificare correttamente costrutti matematici)

  4. la vettorializzazione produce più codice "Pythonic". Senza vettorializzazione, il nostro codice sarebbe disseminato di loop inefficienti e difficili da leggere.


4

La vettorializzazione, in parole semplici, significa ottimizzare l'algoritmo in modo che possa utilizzare le istruzioni SIMD nei processori.

AVX, AVX2 e AVX512 sono i set di istruzioni (Intel) che eseguono la stessa operazione su più dati in un'unica istruzione. per es. AVX512 significa che è possibile operare su 16 valori interi (4 byte) alla volta. Ciò significa che se hai un vettore di 16 numeri interi e vuoi raddoppiare quel valore in ciascun numero intero e quindi aggiungere 10 ad esso. Puoi caricare i valori sul registro generale [a, b, c] 16 volte ed eseguire la stessa operazione oppure puoi eseguire la stessa operazione caricando tutti i 16 valori sui registri SIMD [xmm, ymm] ed eseguire l'operazione una volta. Ciò consente di accelerare il calcolo dei dati vettoriali.

Nella vettorializzazione utilizziamo questo a nostro vantaggio, rimodellando i nostri dati in modo da poter eseguire operazioni SIMD su di esso e accelerare il programma.

L'unico problema con la vettorializzazione sono le condizioni di gestione. Perché le condizioni ramificano il flusso di esecuzione. Questo può essere gestito mascherando. Modellando la condizione in un'operazione aritmetica. per esempio. se vogliamo aggiungere 10 al valore se è maggiore di 100. possiamo farlo entrambi.

if(x[i] > 100) x[i] += 10; // this will branch execution flow.

oppure possiamo modellare la condizione in operazione aritmetica creando un vettore condizione c,

c[i] = x[i] > 100; // storing the condition on masking vector
x[i] = x[i] + (c[i] & 10) // using mask

questo è un esempio molto banale ... quindi, c è il nostro vettore di mascheramento che usiamo per eseguire operazioni binarie basate sul suo valore. Ciò evita la diramazione del flusso di esecuzione e consente la vettorializzazione.

La vettorializzazione è importante quanto la parallelizzazione. Pertanto, dovremmo utilizzarlo il più possibile. Tutti i processori moderni hanno istruzioni SIMD per carichi di lavoro di calcolo pesanti. Possiamo ottimizzare il nostro codice per utilizzare queste istruzioni SIMD usando la vettorializzazione, questo è simile alla parallelizzazione del nostro codice per l'esecuzione su più core disponibili sui processori moderni.

Vorrei partire con la menzione di OpenMP, che consente di vettorializzare il codice usando pragmi. Lo considero un buon punto di partenza. Lo stesso si può dire per OpenACC.


0

Per le persone Intel penso che sia facile da capire.

La vettorizzazione è il processo di conversione di un algoritmo dall'operare su un singolo valore alla volta all'operare su un insieme di valori contemporaneamente . Le moderne CPU forniscono supporto diretto per operazioni vettoriali in cui una singola istruzione viene applicata a più dati (SIMD).

Ad esempio, una CPU con un registro a 512 bit può contenere 16 doppie a 32 bit a precisione singola ed eseguire un singolo calcolo.

16 volte più veloce dell'esecuzione di una singola istruzione alla volta. Combinando questo con il threading e le CPU multi-core si ottengono ordini di aumento delle prestazioni di grandezza.

Link https://software.intel.com/en-us/articles/vectorization-a-key-tool-to-improve-performance-on-modern-cpus

In Java esiste un'opzione da includere in Jdk 15 del 2020 o in ritardo a JDK 16 al 2021.

https://bugs.openjdk.java.net/browse/JDK-8201271


-4

Vedi le due risposte sopra. Volevo solo aggiungere che la ragione per voler fare la vettorializzazione è che queste operazioni possono essere facilmente eseguite in parallelo da supercomputer e multi-processori, ottenendo un grande guadagno in termini di prestazioni. Sui computer con processore singolo non ci saranno miglioramenti delle prestazioni.


12
"Sui computer a singolo processore non ci sarà alcun miglioramento delle prestazioni": non vero. La maggior parte dei processori moderni ha un supporto hardware (limitato) per la vettorializzazione (SSE, Altivec, ecc. Come indicato dal stephentyrone), che può dare una notevole velocità quando usato.
sleske,

grazie, ho dimenticato che la parallelizzazione può essere fatta anche a quel livello.
Larry Watanabe,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.