Qpnc (Q parallel numerical computations)
-
wrote on 23 May 2010, 08:30 last edited by
I have been developing a high level library for parallel numerical computations that uses the signal and slot system provided by Qt. It's goal was to simplify the code one needs to write in order to make use of the power provided by multiprocessor systems. It is still in the need of a code clean up but I would really like to show You its current API.
A part of the Conjugate Gradients method written using Qpnc.
@
void QpncConjugateGradients::buildOperationTree()
{
delete operation;QpncAbstractOperation<double>* qOperation = QpncOperationFactory<double>::produceOperation
(QpncOperations::MULTIPLY,A,d,q);
QpncAbstractOperation<double>* fakeD =
QpncOperationFactory<double>::produceOperation
(QpncOperations::FAKE,d,0,0,0);QpncAbstractOperation<double>* fakeDelta = QpncOperationFactory<double>::produceOperation
(QpncOperations::FAKE,deltaNew,0,0,0);
QpncAbstractOperation<double>* dq =
QpncOperationFactory<double>::produceOperation
(QpncOperations::COMPOSITE_DOT_PRODUCT,
fakeD,qOperation);QpncAbstractOperation<double>* alphaOperation = QpncOperationFactory<double>::produceOperation
(QpncOperations::COMPOSITE_SIGNLE_DIVIDE,fakeDelta,dq,alpha);
QpncAbstractOperation<double>* fakeQ =
QpncOperationFactory<double>::produceOperation
(QpncOperations::FAKE,q,0,0,0);QpncAbstractOperation<double>* fakeR = QpncOperationFactory<double>::produceOperation
(QpncOperations::FAKE,r,0,0,0);
QpncAbstractOperation<double>* alphaQ =
QpncOperationFactory<double>::produceOperation
(QpncOperations::COMPOSITE_SINGLE_MULTIPLY,fakeQ,alphaOperation);QpncAbstractOperation<double>* fakeR2 = QpncOperationFactory<double>::produceOperation
(QpncOperations::FAKE,r,0,0,0);
QpncAbstractOperation<double>* rOperation =
QpncOperationFactory<double>::produceOperation
(QpncOperations::COMPOSITE_SUBSTRACT,fakeR,alphaQ,r);QpncAbstractOperation<double>* deltaNewOperation = QpncOperationFactory<double>::produceOperation
(QpncOperations::COMPOSITE_DOT_PRODUCT,fakeR2,rOperation,deltaNew);
QpncAbstractOperation<double>* fakeDeltaOld =
QpncOperationFactory<double>::produceOperation
(QpncOperations::FAKE,deltaOld,0,0,0);QpncAbstractOperation<double>* betaOperation = QpncOperationFactory<double>::produceOperation
(QpncOperations::COMPOSITE_SIGNLE_DIVIDE,deltaNewOperation,
fakeDeltaOld,beta);
QpncAbstractOperation<double>* fakeD2 =
QpncOperationFactory<double>::produceOperation
(QpncOperations::FAKE,d,0,0,0);QpncAbstractOperation<double>* fakeR3 = QpncOperationFactory<double>::produceOperation
(QpncOperations::FAKE,r,0,0,0);
QpncAbstractOperation<double>* betaD =
QpncOperationFactory<double>::produceOperation
(QpncOperations::COMPOSITE_SINGLE_MULTIPLY,
fakeD2,betaOperation);operation = QpncOperationFactory<double>::produceOperation
(QpncOperations::COMPOSITE_ADD,fakeR3,betaD,dNew);
connect(operation,SIGNAL(finished(int)),this,SLOT(calculateX(int))); operation->start();
}
@And the same written using POSIX
@
void* ThreadFunction(void* in)//rewrite
{
ThreadData* data = (ThreadData*)in;
unsigned iteration = 0;
unsigned pack = data->rowCount / data->threadCount;
unsigned startIndex = data->threadNum * pack;
unsigned endIndex = startIndex + pack;
if(data->threadNum == data->threadCount - 1)
endIndex = data->rowCount;
for(unsigned i = startIndex; i < endIndex; ++i)
{
double AxValue = 0.0;
for(unsigned j = 0; j < data->collumnCount; ++j)
AxValue += data->A[i][j] * data->x[j][0];data->r[i][0] = data->b[i][0] - AxValue; } pthread_barrier_wait(data->barrier); for(unsigned i = startIndex; i < endIndex; ++i) data->d[i][0] = data->r[i][0]; pthread_barrier_wait(data->barrier); double localDelta = 0.0; for(unsigned i = startIndex; i < endIndex; ++i) localDelta += data->r[i][0] * data->r[i][0]; pthread_mutex_lock(data->mutex); *data->deltaNew += localDelta; pthread_mutex_unlock(data->mutex); pthread_barrier_wait(data->barrier); if(data->threadNum == 0) { *data->deltaOld = *data->deltaNew; *data->prec = (*data->eps * *data->eps) * *data->deltaOld; } pthread_barrier_wait(data->globalBarrier); while(iteration < data->iterations && *data->deltaNew > *data->prec) { for(unsigned i = startIndex; i < endIndex; ++i) { double AdValue = 0.0; for(unsigned j = 0; j < data->collumnCount; ++j) AdValue += data->A[i][j] * data->d[j][0]; data->q[i][0] = AdValue; } pthread_barrier_wait(data->barrier); double localValue = 0.0; for(unsigned i = startIndex; i < endIndex; ++i) localValue += data->d[i][0] * data->q[i][0]; pthread_mutex_lock(data->mutex); *data->dq += localValue; pthread_mutex_unlock(data->mutex);
//...
++iteration;
}
return NULL;
}
@When dealing with a task of calculating a system of linear equations composed of a matrix 15000x15000, Qpnc has an efficiency rate of 92%, witch compared to POSIX witch has an efficiency rate of 95% is not a bad result.
-
wrote on 27 May 2010, 18:20 last edited by
are you planned to release this soon???
-
wrote on 28 May 2010, 07:48 last edited by
As this is a part of my Master's Thesis, witch I'll be hopefully defending somewhere next month. I'm planning to release it by July.
-
wrote on 27 Aug 2010, 14:44 last edited by
Ok so I successfully defended my masters thesis, but couldn't find the time to make an API clean-up. I would like to know if there is someone interested in trying to use my work under an GPL or BSD-like licence. I would also by thankful if someone could point me to a place where I could publish it.
-
wrote on 30 Aug 2010, 05:16 last edited by
[quote author="kkrzewniak" date="1282920261"]I would like to know if there is someone interested in trying to use my work under an GPL or BSD-like licence.[/quote]
Sometimes supply creates demand
[quote author="kkrzewniak" date="1282920261"]I would also by thankful if someone could point me to a place where I could publish it.[/quote]
-
wrote on 20 Oct 2010, 07:32 last edited by
Qpnc Code is now live on sourceforge.net
"https://qpnc.svn.sourceforge.net/svnroot/qpnc":https://qpnc.svn.sourceforge.net/svnroot/qpnc