Ich implementiere einen Echtzeit-Signalverarbeitungsalgorithmus in C und ich versuche, einen Teil des Codes mit Multithreading zu parallelisieren.Multithread führt zu einer langsameren Leistung in C
Der Code für die Single-Threaded-Implementierung ist
void calcTheta(float *theta, float **s, float ***q, float ***g,
int *Ki, int m, int numObv, int numTask) {
int i, j, k;
for (i = 0; i < m; i++) {
theta[i] = 0;
for (j = 0; j < numObv; j++) {
for (k = 0; k < numTask; k++) {
theta[i] += (Ki[k] * (pow(fabs(q[i][j][k]), 2)/g[i][j][k]) - s[i][k])/
(s[i][k] * (s[i][k] - (pow(fabs(q[i][j][k]), 2)/g[i][j][k])));
}//k
}//j
theta[i] = (numTask * numObv)/theta[i];
}//i
}
Die multithreaded Implementierung verwendet Idee, einen Thread-Spooling wo ich einige Threads erzeugen und halten sie mit spezifischen Signalisierungsdatenfelder zu verarbeiten. Der Code ist unten:
#define NUM_THREADS_THETA 2
#define TRUE 1
#define FALSE 0
#define READY 1
#define DONE 0
struct threadThetaData {
float *theta;
float **s;
float ***q;
float ***g;
int *Ki;
int numObv;
int numTask;
int threadId;
};
struct threadThetaData dataArrayTheta[NUM_THREADS_THETA];
int termThread[NUM_THREADS_THETA];
int statusThread[NUM_THREADS_THETA];
int iVal[NUM_THREADS_THETA];
pthread_mutex_t mutexThreadProc[NUM_THREADS_THETA];
pthread_mutex_t mutexMainProc[NUM_THREADS_THETA];
pthread_cond_t condThreadProc[NUM_THREADS_THETA];
pthread_cond_t condMainProc[NUM_THREADS_THETA];
void *doProcTheta(void *threadArg) {
struct threadThetaData *myData = (struct threadThetaData *)threadArg;
float *theta = myData->theta;
float **s = myData->s;
float ***q = myData->q;
float ***g = myData->g;
int *Ki = myData->Ki;
int numObv = myData->numObv;
int numTask = myData->numTask;
int threadId = myData->threadId;
int j, k;
while(1) {
//printf("thread %d waiting for signal from master..\n", threadId);
pthread_mutex_lock(&mutexThreadProc[threadId]);
while (statusThread[threadId] != READY)
pthread_cond_wait(&condThreadProc[threadId], &mutexThreadProc[threadId]);
pthread_mutex_unlock(&mutexThreadProc[threadId]);
//printf("thread %d got signal from master..\n", threadId);
if (termThread[threadId] == TRUE)
pthread_exit(NULL);
theta[iVal[threadId]] = 0;
for (j = 0; j < numObv; j++) {
for (k = 0; k < numTask; k++) {
theta[iVal[threadId]] += (Ki[k]*(pow(fabs(q[iVal[threadId]][j][k]),2)/g[iVal[threadId]][j][k]) - s[iVal[threadId]][k])/(s[iVal[threadId]][k]*(s[iVal[threadId]][k] - (pow(fabs(q[iVal[threadId]][j][k]),2)/g[iVal[threadId]][j][k])));
}//k
}//j
theta[iVal[threadId]] = (numTask*numObv)/theta[iVal[threadId]];
pthread_mutex_lock(&mutexMainProc[threadId]);
statusThread[threadId] = DONE;
pthread_cond_signal(&condMainProc[threadId]);
pthread_mutex_unlock(&mutexMainProc[threadId]);
//printf("thread %d signaled to master..\n", threadId);
}
}
void calcTheta(float *theta,float **s,float ***q,float ***g,int *Ki,int m, int numObv, int numTask)
{
int i,j;
pthread_t thetaThreads[NUM_THREADS_THETA];
int numThreadBlks = m/NUM_THREADS_THETA;
int numThreadRem = m%NUM_THREADS_THETA;
int mCount = 0;
for(i=0;i<NUM_THREADS_THETA;i++)
{
pthread_mutex_init(&mutexThreadProc[i], NULL);
pthread_mutex_init(&mutexMainProc[i], NULL);
pthread_cond_init (&condThreadProc[i], NULL);
pthread_cond_init (&condMainProc[i], NULL);
dataArrayTheta[i].theta = theta;
dataArrayTheta[i].s = s;
dataArrayTheta[i].q = q;
dataArrayTheta[i].g = g;
dataArrayTheta[i].Ki = Ki;
dataArrayTheta[i].numObv = numObv;
dataArrayTheta[i].numTask = numTask;
dataArrayTheta[i].threadId = i;
termThread[i] = FALSE;
statusThread[i] = DONE;
pthread_create(&thetaThreads[i],NULL,doProcTheta,(void *)&dataArrayTheta[i]);
}
for(i=0;i<numThreadBlks;i++)
{
for(j=0;j<NUM_THREADS_THETA;j++)
{
pthread_mutex_lock(&mutexThreadProc[j]);
statusThread[j] = READY;
iVal[j] = mCount;
mCount++;
pthread_cond_signal(&condThreadProc[j]);
pthread_mutex_unlock(&mutexThreadProc[j]);
//printf("Signaled thread %d from master ... Waiting on signal ..\n",j);
}
for(j=0;j<NUM_THREADS_THETA;j++)
{
pthread_mutex_lock(&mutexMainProc[j]);
while (statusThread[j] != DONE)
pthread_cond_wait(&condMainProc[j], &mutexMainProc[j]);
pthread_mutex_unlock(&mutexMainProc[j]);
//printf("Got signal from thread %d to master \n",j);
}
}
for(j=0;j<numThreadRem;j++)
{
pthread_mutex_lock(&mutexThreadProc[j]);
statusThread[j] = READY;
iVal[j] = mCount;
mCount++;
pthread_cond_signal(&condThreadProc[j]);
pthread_mutex_unlock(&mutexThreadProc[j]);
}
for(j=0;j<numThreadRem;j++)
{
pthread_mutex_lock(&mutexMainProc[j]);
while (statusThread[j] != DONE)
pthread_cond_wait(&condMainProc[j], &mutexMainProc[j]);
pthread_mutex_unlock(&mutexMainProc[j]);
}
for(j=0;j<NUM_THREADS_THETA;j++)
{
pthread_mutex_lock(&mutexThreadProc[j]);
statusThread[j] = READY;
termThread[j] = TRUE;
pthread_cond_signal(&condThreadProc[j]);
pthread_mutex_unlock(&mutexThreadProc[j]);
pthread_join(thetaThreads[j],NULL);
pthread_mutex_destroy(&mutexThreadProc[j]);
pthread_cond_destroy(&condThreadProc[j]);
pthread_mutex_destroy(&mutexMainProc[j]);
pthread_cond_destroy(&condMainProc[j]);
}
}
Array Dimensionen:
float theta[m];
float s[m][numTask];
float q[m][numObv][numTask];
float g[m][numObv][numTask];
int Ki[numTask];
Für eine bestimmte Datenmenge in dem
m=661
numObv=96
numTask=1024
die Laufzeiten sind:
Single threaded : 4.5 seconds
Multithreaded with 2 threads : 6.9 seconds
ich erwartet, dass die Laufzeiten für der Multithread-Code zu gib mir etwas Performance-Verbesserung gegenüber dem Single-Thread-Code, wenn es umgekehrt ist. Irgendwelche Hinweise darauf, was ich hier vermisse, wären sehr willkommen.
Nicht genügend Arbeit zwischen den Sperren führt zu mehr Zeit, die mit Sperren verbracht wird, als mit zeitsparender Parallelverarbeitung. – chqrlie
Ich kann die Berechnung von Theta in der DoProcTheta-Funktion in das Schloss verschieben, würde das helfen ?? – anshu
Nur lose auf Ihre Frage bezogen: Wenn Sie es noch nicht wissen, schauen Sie sich OpenMP an. – Phillip