Sto cercando di imparare le funi delle intrinseche SSE in C. Ho un pezzo di codice in cui carico un vettore a due componenti di dati doppi, aggiungo qualcosa e poi cerco di memorizzarlo torna alla memoria. Tutto funziona: posso caricare i miei dati nei registri SEE, posso operare sui miei dati in quei registri SSE, ma nel momento in cui provo a scrivere i dati elaborati nell'array originale (che è il punto in cui ho letto i miei dati da primo posto!) Ottengo un errore di segmentazione.SSE _mm_load_pd funziona mentre _mm_store_pd segfaults
Qualcuno può consigliarmi su questo argomento - questo mi sta facendo impazzire.
double res[2] __attribute__((aligned(16)));
for(int k=0; k<n; k++){
int i=0;
for(; i+1<n; i+=2)
{
__m128d cik = _mm_load_pd(&C[i+k*n]);
int j = 0;
for(; j+1<n; j+=2)
{
__m128d aTij = _mm_load_pd(&A_T[j+i*n]);
__m128d bjk = _mm_load_pd(&B[j+k*n]);
__m128d dotpr = _mm_dp_pd(aTij, bjk,2);
cik = _mm_add_pd(cik, dotpr);
}
_mm_store_pd(res, cik);
//C[i+k*n] = res[0];
}
}
Come ho già detto in precedenza, tutto funziona in questo codice eccezione di dove posso conservare i miei risultati indietro a quella matrice unidimensionale "C" dove ho letto i miei dati da in primo luogo. Cioè, quando ho rimuovere il commento segni di fronte
//C[i+k*n] = res[0];
ottengo un segmentation fault.
Come è possibile che io possa leggere da C con la versione di memoria allineata di _mm_load_pd (quindi C deve essere allineato in memoria!) Mentre la scrittura su di esso non funziona? "C" deve essere allineato e, come puoi vedere, "res" deve essere allineato.
responsabilità: mio codice originale leggere
_mm_store_pd(&C[i+k*n], cik);
che ha prodotto anche un errore di segmentazione e ho iniziato l'introduzione di "res" con l'allineamento esplicito nel mio tentativo di risolvere il problema.
Addendum
A, B, C sono dichiarati come segue:
buf = (double*) malloc (3 * nmax * nmax * sizeof(double));
double* A = buf + 0;
double* B = A + nmax*nmax;
double* C = B + nmax*nmax;
tentata soluzione con posix_memalign
Nel tentativo di risolvere il problema di errore di segmentazione quando si scrive al array monodimensionale originale, ora utilizzo i buffer per le matrici corrispondenti. Tuttavia, questo seg segna ancora quando si tenta di riscrivere su C_buff!
double res[2] __attribute__((aligned(16)));
double * A_T;
posix_memalign((void**)&A_T, 16, n*n*sizeof(double));
double * B_buff;
posix_memalign((void**)&B_buff, 16, n*n*sizeof(double));
double * C_buff;
posix_memalign((void**)&C_buff, 16, n*n*sizeof(double));
for(int y=0; y<n; y++)
for(int x=0; x<n; x++)
A_T[x+y*n] = A[y+x*n];
for(int x=0; x<n; x++)
for(int y=0; y<n; y++)
B_buff[y+x*n] = B[y+x*n];
for(int x=0; x<n; x++)
for(int y=0; y<n; y++)
C_buff[y+x*n] = C[y+x*n];
for(int k=0; k<n; k++){
int i=0;
for(; i+1<n; i+=2)
{
__m128d cik = _mm_load_pd(&C_buff[i+k*n]);
int j = 0;
for(; j+1<n; j+=2)
{
__m128d aTij = _mm_load_pd(&A_T[j+i*n]);
__m128d bjk = _mm_load_pd(&B_buff[j+k*n]);
__m128d dotpr = _mm_dp_pd(aTij, bjk,2);
cik = _mm_add_pd(cik, dotpr);
}
_mm_store_pd(&C_buff[i+k*n], cik);
//_mm_store_pd(res, cik);
//C_buff[i+k*n] = res[0];
//C_buff[i+1+k*n] = res[1];
}
}
Come viene dichiarato 'C'? –
@TonyTheLion si prega di consultare l'addendum in questione. Per quanto ho capito, malloc tenta di allineare il pezzo di memoria che alloca ma non sempre riesce a tutti gli effetti. Il mio principale punto di confusione su quanto sopra è che posso leggere da quella particolare posizione in "C" ma non riesco a scriverlo. Quindi "C" appare allineata allo scopo di leggere ma non scrivere? –
Penso che partendo dal presupposto che 'malloc' allineerà qualcosa è incerto, potresti voler usare [' aligned_alloc'] (http://man7.org/linux/man-pages/man3/posix_memalign.3.html) se stai usando GCC o ['_aligned_malloc'] (http://msdn.microsoft.com/en-us/library/8z34s9c6%28VS.80%29.aspx) se stai usando MSVC. –