Sto cercando di accelerare la moltiplicazione della matrice su architettura multicore. Per questo scopo, cerco di utilizzare thread e SIMD contemporaneamente. Ma i miei risultati non sono buoni. I test accelerare sopra sequenziale moltiplicazione matriciale:parallelizzazione della moltiplicazione della matrice tramite threading e SIM
void sequentialMatMul(void* params)
{
cout << "SequentialMatMul started.";
int i, j, k;
for (i = 0; i < N; i++)
{
for (k = 0; k < N; k++)
{
for (j = 0; j < N; j++)
{
X[i][j] += A[i][k] * B[k][j];
}
}
}
cout << "\nSequentialMatMul finished.";
}
Ho provato ad aggiungere filettatura e SIMD alla matrice di moltiplicazione come segue:
void threadedSIMDMatMul(void* params)
{
bounds *args = (bounds*)params;
int lowerBound = args->lowerBound;
int upperBound = args->upperBound;
int idx = args->idx;
int i, j, k;
for (i = lowerBound; i <upperBound; i++)
{
for (k = 0; k < N; k++)
{
for (j = 0; j < N; j+=4)
{
mmx1 = _mm_loadu_ps(&X[i][j]);
mmx2 = _mm_load_ps1(&A[i][k]);
mmx3 = _mm_loadu_ps(&B[k][j]);
mmx4 = _mm_mul_ps(mmx2, mmx3);
mmx0 = _mm_add_ps(mmx1, mmx4);
_mm_storeu_ps(&X[i][j], mmx0);
}
}
}
_endthread();
}
E la sezione seguente viene utilizzata per calcolare lowerbound e limitesuperiore di ogni filo :
bounds arg[CORES];
for (int part = 0; part < CORES; part++)
{
arg[part].idx = part;
arg[part].lowerBound = (N/CORES)*part;
arg[part].upperBound = (N/CORES)*(part + 1);
}
E infine filettato versione SIMD viene chiamato in questo modo:
HANDLE handle[CORES];
for (int part = 0; part < CORES; part++)
{
handle[part] = (HANDLE)_beginthread(threadedSIMDMatMul, 0, (void*)&arg[part]);
}
for (int part = 0; part < CORES; part++)
{
WaitForSingleObject(handle[part], INFINITE);
}
Il risultato è il seguente: Test 1:
// arrays are defined as follow
float A[N][N];
float B[N][N];
float X[N][N];
N=2048
Core=1//just one thread
tempo sequenziale: 11129ms
filettato SIMD tempo matmul: 14650ms
Accelerare = 0,75x
test 2:
//defined arrays as follow
float **A = (float**)_aligned_malloc(N* sizeof(float), 16);
float **B = (float**)_aligned_malloc(N* sizeof(float), 16);
float **X = (float**)_aligned_malloc(N* sizeof(float), 16);
for (int k = 0; k < N; k++)
{
A[k] = (float*)malloc(cols * sizeof(float));
B[k] = (float*)malloc(cols * sizeof(float));
X[k] = (float*)malloc(cols * sizeof(float));
}
N=2048
Core=1//just one thread
tempo sequenziale: 15907ms
filettato SIMD tempo matmul: 18578ms
Accelerare = 0.85x
Test 3:
//defined arrays as follow
float A[N][N];
float B[N][N];
float X[N][N];
N=2048
Core=2
tempo sequenziale: 10855ms
filettato SIMD matmul time: 27967ms
Accelerare = 0.38x
Test 4:
//defined arrays as follow
float **A = (float**)_aligned_malloc(N* sizeof(float), 16);
float **B = (float**)_aligned_malloc(N* sizeof(float), 16);
float **X = (float**)_aligned_malloc(N* sizeof(float), 16);
for (int k = 0; k < N; k++)
{
A[k] = (float*)malloc(cols * sizeof(float));
B[k] = (float*)malloc(cols * sizeof(float));
X[k] = (float*)malloc(cols * sizeof(float));
}
N=2048
Core=2
tempo sequenziale: 16579ms
filettato SIMD tempo matmul: 30160ms
Accelerare = 0.51x
mio domanda: perché non ottengo velocità?
immagino che l'attuazione naif di moltiplicazione di matrici (che usa direttamente la definizione del prodotto) non si traduce troppo bene al al SIMD. Nella prima parallelizzazione, il valore 'A [i] [k]' deve essere copiato in tutti e quattro i componenti del registro. La voce desiderata X [i] [j] 'può essere espressa come la somma dei prodotti della riga' i'-di 'A' con la colonna' j'-th di 'B'. Se 'B' fosse memorizzato in termini di colonne anziché di riga, il parallelismo potrebbe essere applicato in un modo più diretto e sarebbe anche più facile da usare nella cache. – Codor
[openmp-c-matrix-multiplication-run-slow-in-parallel] (https://stackoverflow.com/questions/22634121/openmp-c-matrix-multiplication-run-slower-in-parallel/22637933#22637933) –
Quando si definiscono gli array anziché il puntatore agli array, presumo che si stiano utilizzando array globali (se così fosse li renderei statici) perché lo stack è troppo piccolo per gli array 2048x2048. –