SlideShare une entreprise Scribd logo
1  sur  25
Télécharger pour lire hors ligne
C++	
  User	
  Group	
  Mee-ng,	
  Nizhniy	
  Novgorod,	
  19.04.14	
  
Опыт	
  внедрения	
  технологий	
  параллельных	
  вычислений	
  
для	
  повышения	
  производительности	
  численных	
  расчетов	
  
Крутько	
  Е.С.	
  
НИЦ	
  «Курчатовский	
  институт»	
  
e.s.krutko@gmail.com	
  
План	
  презентации	
  
•  Рассмотрение	
  кода	
  программы	
  моделирования	
  динамики	
  
твердого	
  тела	
  по	
  методу	
  конечных	
  элементов	
  
•  Использование	
  openmp	
  
•  Явное	
  создание	
  вычислительных	
  потоков	
  
•  Использование	
  MPI	
  
•  Комбинированный	
  подход	
  
Репозиторий	
  проекта:	
  
hnps://github.com/eskrut/directIntegra-onSolver.git	
  
2	
  
Кратко	
  о	
  теории	
  
M¨q + C ˙q + Kq = f
q = {dx0, dy0, dz0, · · · dxN 1, dyN 1, dzN 1}T
M =
0
B
B
B
@
m0 0 0 0
0 m1 0 0
0 0
... 0
0 0 0 mN 1
1
C
C
C
A
C = ⇠M
˙q =
qt+ t qt t
2 t
, ¨q =
qt+ t 2qt + qt t
2 t
qt+ t(a0M + a1C) = f Kq + a2Mqt (a0M a1C)qt t
Задача	
   решается	
   по	
   методу	
  
к о н е ч н ы х	
   э л е м е н т о в	
   с	
  
использованием	
   явной	
   схемы	
  
интегрирования	
   по	
   времени.	
  
Вся	
   необходимая	
   логика	
   МКЭ	
  
реализована	
   во	
   внешней	
  
библиотеке,	
  необходимо	
  только	
  
построить	
   на	
   ее	
   основе	
  
решатель.	
  
3	
  
Объект	
  исследования	
  
~250	
  000	
  	
  узлов	
  
4	
  
Ветка:	
  
Коммит:	
  
Основной	
  код	
  программы	
  
master	
  
9f49d14	
  
int main(int argc, char ** argv)!
{!
int discretParam, numOutput;!
double t, tStop, dt, dtOut, tNextOut, transT;!
double ampX, freqX, ksi;!
bool recreateMesh = false;!
bool makeNodesRenumbering = true;!
po::options_description desc("Program options");!
desc.add_options()!
("help,h", "print help message")!
("dt", po::value<double>(&dt)->default_value(1e-5), "integration time step")!
("tStop,t", po::value<double>(&tStop)->default_value(1e1), "time range")!
("transT", po::value<double>(&transT)->default_value(1e-3), "load transition time")!
("ampX,a", po::value<double>(&ampX)->default_value(1e-3), "displacement amplitude")!
("freqX,f", po::value<double>(&freqX)->default_value(1e0), "displacement frequency [Hz]")!
("ksi,k", po::value<double>(&ksi)->default_value(1e-1), "damping factor")!
("numOutput,n", po::value<int>(&numOutput)->default_value(500), "number of outputs")!
("discretParam,d", po::value<int>(&discretParam)->default_value(2), "discretisation parameter")!
("recreateMesh,m", "recreate mesh")!
("no-nr", "do not optimize nodes numbering")!
;!
po::variables_map vm;!
po::store(po::parse_command_line(argc, argv, desc), vm);!
po::notify(vm);!
if (vm.count("help") || vm.count("h")) { std::cout << desc << "n"; return 1; }!
if (vm.count("recreateMesh") || vm.count("m")) { recreateMesh = true; }!
if (vm.count("no-nr")) { makeNodesRenumbering = false; }!
!
t = tNextOut = 0;!
dtOut = tStop/numOutput;!
double a0, a1, a2;!
a0 = 1.0/(dt*dt); a1 = 1.0/(2.0*dt); a2 = 2.0*a0;
5	
  
Ветка:	
  
Коммит:	
  
Основной	
  код	
  программы	
  
master	
  
9f49d14	
  
// Create appropriate mesh!
std::unique_ptr<sbfMesh> meshPtr(new sbfMesh);!
if( recreateMesh || meshPtr->readMeshFromFiles() ){!
meshPtr.reset(createMesh(discretParam));!
if ( makeNodesRenumbering ) meshPtr->optimizeNodesNumbering();!
meshPtr->writeMeshToFiles();!
}!
sbfMesh *mesh = meshPtr.get();!
const int numNodes = mesh->numNodes();!
!
// Create and compute stiffness matrix!
std::unique_ptr<sbfStiffMatrixBlock3x3> stiffPtr(createStiffMatrix(mesh, recreateMesh));!
sbfStiffMatrixBlock3x3 *stiff = stiffPtr.get();!
!
// Create nodes data storages!
NodesData<double, 3> displ_m1(mesh), displ("displ", mesh), displ_p1(mesh);!
NodesData<double, 3> force(mesh), mass("mass", mesh), demp(mesh), rezKU(mesh);!
mass.null(); force.null(); demp.null(); displ_m1.null(); displ.null();!
!
// Fill mass and demping arrays!
computeMassDemp(mass, demp, mesh, stiff->propSet(), ksi, recreateMesh);!
!
// Get indexes of kinematic loaded nodes!
std::vector<int> loadedNodesDown, loadedNodesUp;!
double maxY = mesh->maxY();!
for(int ct = 0; ct < numNodes; ct++){!
if( std::fabs(mesh->node(ct).y()) < 1e-5) loadedNodesDown.push_back(ct);!
if( std::fabs(mesh->node(ct).y() - maxY) < 1e-5 ) loadedNodesUp.push_back(ct);!
}!
const int numLDown = loadedNodesDown.size(), numLUp = loadedNodesUp.size();!
!
// Stiffness matrix iteration halper!
std::unique_ptr<sbfMatrixIterator> iteratorPtr(stiff->createIterator());!
sbfMatrixIterator *iterator = iteratorPtr.get();
6	
  
Ветка:	
  
Коммит:	
  
Основной	
  код	
  программы	
  
master	
  
9f49d14	
  
// Time integration loop!
report.createNewProgress("Time integration");!
while( t < tStop ) { // Time loop!
// Update displacements of kinematically loaded nodes!
double tmp[3], temp; getDispl(t, tmp, ampX, freqX, transT);!
for(int nodeCt = 0; nodeCt < numLDown; ++nodeCt) for(int ct = 0; ct < 3; ct++)!
displ.data(loadedNodesDown[nodeCt], ct) = tmp[ct];!
for(int nodeCt = 0; nodeCt < numLUp; ++nodeCt) for(int ct = 0; ct < 3; ct++)!
displ.data(loadedNodesUp[nodeCt], ct) = tmp[ct]/3;!
!
for(int nodeCt = 0; nodeCt < numNodes; nodeCt++) {!
// Make multiplication of stiffness matrix over displacement vector!
iterator->setToRow(nodeCt);!
double *rez = rezKU.data() + nodeCt*3;!
rez[0] = rez[1] = rez[2] = 0.0;!
while(iterator->isValid()) {!
int columnID = iterator->column();!
double *vectPart = displ.data() + columnID*3;!
double *block = iterator->data();!
for(int rowCt = 0; rowCt < 3; ++rowCt)!
for(int colCt = 0; colCt < 3; ++colCt)!
rez[rowCt] += block[rowCt*3+colCt]*vectPart[colCt];!
iterator->next();!
}!
// Perform finite difference step!
for(int ct = 0; ct < 3; ct++) {!
temp=force.data(nodeCt, ct) - rezKU.data(nodeCt, ct) +!
a2*mass.data(nodeCt, ct)*displ.data(nodeCt, ct) -!
(a0*mass.data(nodeCt, ct) - a1*demp.data(nodeCt, ct))*displ_m1.data(nodeCt, ct);!
displ_p1.data(nodeCt, ct) = temp/(a0*mass.data(nodeCt, ct) + a1*demp.data(nodeCt, ct));!
}!
}!
// Make output if required!
if(t >= tNextOut) { displ.writeToFile();tNextOut += dtOut;report.updateProgress(t/tStop*100);}!
// Prepere for next step!
t += dt;!
displ_m1.copyData(displ); displ.copyData(displ_p1);!
} // End time loop!
report.finalizeProgress();!
return 0; 7	
  
Ветка:	
  
Коммит:	
  
Поиск	
  узкого	
  места	
  
master	
  
6d51e09	
  
// Time integration loop!
report.createNewProgress("Time integration");!
std::chrono::nanoseconds period1(0), period2(0), period3(0), period4(0);!
while( t < tStop ) { // Time loop!
auto timePoint_0 = Clock::now();!
// Update displacements of kinematically loaded nodes!
// .... //!
auto timePoint_1 = Clock::now();!
for(int nodeCt = 0; nodeCt < numNodes; nodeCt++) {!
// Make multiplication of stiffness matrix over displacement vector!
// .... //!
}!
auto timePoint_2 = Clock::now();!
for(int nodeCt = 0; nodeCt < numNodes; nodeCt++) {!
// Perform finite difference step!
// .... //!
}!
auto timePoint_3 = Clock::now();!
// Make output if required!
// Prepere for next step!
// .... //!
auto timePoint_4 = Clock::now();!
period1 += std::chrono::duration_cast<std::chrono::nanoseconds>(timePoint_1 - timePoint_0);!
period2 += std::chrono::duration_cast<std::chrono::nanoseconds>(timePoint_2 - timePoint_1);!
period3 += std::chrono::duration_cast<std::chrono::nanoseconds>(timePoint_3 - timePoint_2);!
period4 += std::chrono::duration_cast<std::chrono::nanoseconds>(timePoint_4 - timePoint_3);!
} // End time loop!
report.finalizeProgress();!
!
report("Prepare part time : ", period1.count());!
report("Matrix multiplication time : ", period2.count());!
report("Finite difference step time : ", period3.count());!
report("Finilizing part time : ", period4.count());!
!
Вывод:
Prepare part time : 26608769!
Matrix multiplication time : 87985118534!
Finite difference step time : 7031352999!
Finilizing part time : 2039084873! 8	
  
OpenMP	
  
OpenMP	
   (Open	
   Mul--­‐Processing)	
   —	
   открытый	
   стандарт	
   для	
   распараллеливания	
  
программ	
   на	
   языках	
   Си,	
   Си++	
   и	
   Фортран.	
   Описывает	
   совокупность	
   директив	
  
компилятора,	
   библиотечных	
   процедур	
   и	
   переменных	
   окружения,	
   которые	
  
предназначены	
   для	
   программирования	
   многопоточных	
   приложений	
   на	
  
многопроцессорных	
  системах	
  с	
  общей	
  памятью	
  //Wikipedia	
  
#pragma	
  omp	
  parallel	
  
#pragma	
  omp	
  for	
  
#pragma	
  omp	
  sec-ons	
  
#pragma	
  omp	
  single	
  
#pragma	
  omp	
  parallel	
  for	
  
#pragma	
  omp	
  parallel	
  sec-ons	
  
#pragma	
  omp	
  task	
  
#pragma	
  omp	
  master	
  
#pragma	
  omp	
  cri-cal	
  
#pragma	
  omp	
  barrier	
  
	
  
void	
  omp_set_num_threads(int	
  );	
  
int	
  omp_get_num_threads(void);	
  
int	
  omp_get_max_threads(void);	
  
int	
  omp_get_thread_num(void);	
  
int	
  omp_get_num_procs(void);	
  
int	
  omp_in_parallel(void);	
  
void	
  omp_set_dynamic(int	
  );	
  
void	
  omp_set_lock(omp_lock_t	
  *);	
  
int	
  omp_test_lock(omp_lock_t	
  *);	
  
	
  
	
  
OMP_SCHEDULE	
  type[,chunk]	
  
OMP_NUM_THREADS	
  num	
  
OMP_DYNAMIC	
  dynamic	
  
OMP_NESTED	
  nested	
  
OMP_STACKSIZE	
  size	
  
OMP_WAIT_POLICY	
  policy	
  
OMP_MAX_ACTIVE_LEVELS	
  levels	
  
OMP_THREAD_LIMIT	
  limit	
  
9	
  
Ветка:	
  
Коммит:	
  
Первая	
  попытка	
  с	
  openMP	
  (не	
  работает)	
  
openMP	
  
99940bc	
  
CMakeLists.txt!
!
find_package(OpenMP REQUIRED)!
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")!
!
main.cpp!
!
#include <omp.h>!
// ... //!
// Stiffness matrix iteration halper!
std::unique_ptr<sbfMatrixIterator> iteratorPtr(stiff->createIterator());!
sbfMatrixIterator *iterator = iteratorPtr.get();!
!
// Time integration loop!
report.createNewProgress("Time integration");!
while( t < tStop ) { // Time loop!
// Update displacements of kinematically loaded nodes!
// ... //!
#pragma omp parallel for!
for(int nodeCt = 0; nodeCt < numNodes; nodeCt++) {!
// Make multiplication of stiffness matrix over displacement vector!
iterator->setToRow(nodeCt);!
// ... //!
while(iterator->isValid()) {!
// ... //!
iterator->next();!
}!
// Perform finite difference step!
for(int ct = 0; ct < 3; ct++) {!
temp=force.data(nodeCt, ct) // ... //;!
displ_p1.data(nodeCt, ct) = temp/(a0*mass.data(nodeCt, ct)// ... //);!
}!
}!
// Make output if required!
// Prepere for next step!
} // End time loop 10	
  
Ветка:	
  
Коммит:	
  
Нормальная	
  работа	
  openMP	
  
openMP	
  
	
  3f10371	
  
// Time integration loop!
report.createNewProgress("Time integration");!
while( t < tStop ) { // Time loop!
double tmp[3], temp;!
// Update displacements of kinematically loaded nodes!
// ... //!
#pragma omp parallel private(temp)!
{!
// Stiffness matrix iteration halper!
std::unique_ptr<sbfMatrixIterator> iteratorPtr(stiff->createIterator());!
sbfMatrixIterator *iterator = iteratorPtr.get();!
#pragma omp for!
for(int nodeCt = 0; nodeCt < numNodes; nodeCt++) {!
// Make multiplication of stiffness matrix over displacement vector!
iterator->setToRow(nodeCt);!
// ... //!
while(iterator->isValid()) {!
// ... //!
iterator->next();!
}!
// Perform finite difference step!
for(int ct = 0; ct < 3; ct++) {!
temp=force.data(nodeCt, ct) - rezKU.data(nodeCt, ct) +!
a2*mass.data(nodeCt, ct)*displ.data(nodeCt, ct) -!
(a0*mass.data(nodeCt, ct) - a1*demp.data(nodeCt, ct))*displ_m1.data(nodeCt, ct);!
displ_p1.data(nodeCt, ct) = temp/(a0*mass.data(nodeCt, ct) + a1*demp.data(nodeCt, ct));!
}!
}//End of #pragma omp for!
}//End of #pragma omp parallel!
// Make output if required!
// Prepere for next step!
} // End time loop
11	
  
Ветка:	
  
Коммит:	
  
Реорганизация	
  области	
  параллельности	
  
openMP	
  
	
  4579611	
  
// Time integration loop!
double tmp[3];!
#pragma omp parallel!
{!
// Stiffness matrix iteration halper!
std::unique_ptr<sbfMatrixIterator> iteratorPtr(stiff->createIterator());!
sbfMatrixIterator *iterator = iteratorPtr.get();!
while( t < tStop ) { // Time loop!
// Update displacements of kinematically loaded nodes!
#pragma omp master!
getDispl(t, tmp, ampX, freqX, transT);!
#pragma omp for nowait!
for(int nodeCt = 0; nodeCt < numLDown; ++nodeCt) for(int ct = 0; ct < 3; ct++)!
displ.data(loadedNodesDown[nodeCt], ct) = tmp[ct];!
#pragma omp for!
for(int nodeCt = 0; nodeCt < numLUp; ++nodeCt) for(int ct = 0; ct < 3; ct++)!
displ.data(loadedNodesUp[nodeCt], ct) = tmp[ct]/3;!
#pragma omp for!
for(int nodeCt = 0; nodeCt < numNodes; nodeCt++) {!
// Make multiplication of stiffness matrix over displacement vector!
iterator->setToRow(nodeCt);!
// ... //!
while(iterator->isValid()) {!
// ... //!
iterator->next();!
}!
// Perform finite difference step!
for(int ct = 0; ct < 3; ct++)!
// ... //!
}//End of #pragma omp for!
#pragma omp master!
{// Make output if required!
t += dt;}//End of #pragma omp master!
#pragma omp for!
for(int nodeCt = 0; nodeCt < numNodes; nodeCt++) {!
// Prepere for next step!
for(int ct = 0; ct < 3; ct++) {!
displ_m1.data()[3*nodeCt+ct] = displ.data()[3*nodeCt+ct];}!
}//End of #pragma omp for!
} // End time loop!
}//End of #pragma omp parallel 12	
  
Ветка:	
  
Коммит:	
  
Параллельное	
  выполнение	
  секций	
  кода	
  
openMP	
  
	
  84f7a19	
  
sbfMesh *mesh = new sbfMesh, tmp;!
std::unique_ptr<sbfMesh> c(new sbfMesh);!
std::unique_ptr<sbfMesh> plus(new sbfMesh);!
#pragma omp parallel sections private(tmp)!
{!
#pragma omp section!
{!
//Construct C letter!
std::unique_ptr<sbfMesh> roundInner(sbfMesh::makeCylinderPart(1,2,0,2*std::atan(1),0,1,d,2*d,d));!
std::unique_ptr<sbfMesh> roundOuter(sbfMesh::makeCylinderPart(5,6,0,2*std::atan(1),0,1,d,8*d,d));!
std::unique_ptr<sbfMesh> round(new sbfMesh);!
round->addMesh(roundInner.get());!
round->addMesh(roundOuter.get());!
std::unique_ptr<sbfMesh> part0(sbfMesh::makeBlock(4, 1, 1, 4*d, d, d));!
std::unique_ptr<sbfMesh> part4(sbfMesh::makeBlock(3, 1, 1, 3*d, d, d));!
part0->translate(0, 4, 0);!
c->addMesh(part0.get());!
tmp = *round.get();!
tmp.translate(4, 19, 0);!
c->addMesh(tmp);!
// ... ///!
}//End of #pragma omp section!
!
#pragma omp section!
{!
//Construct plus sign!
std::unique_ptr<sbfMesh> part10(sbfMesh::makeBlock(11, 1, 1, 11*d, d, d));!
std::unique_ptr<sbfMesh> part11(sbfMesh::makeBlock(1, 3, 1, d, 3*d, d));!
std::unique_ptr<sbfMesh> part12(sbfMesh::makeBlock(10, 1, 1, 10*d, d, d));!
part11->translate(0, 1, 0);!
part12->translate(0, 4, 0);!
tmp = *part10.get();!
// ... //!
}//End of #pragma omp section!
}//End of#pragma omp parallel sections private(tmp) 13	
  
Явное	
  создание	
  отдельных	
  вычислительных	
  потоков	
  
Основные	
  инструменты	
  работы	
  с	
  потоками:	
  
•  POSIX	
  /	
  WinAPI	
  
•  boost::thread	
  
•  std::thread	
  
14	
  
Ветка:	
  
Коммит:	
  
Создание	
  новых	
  потоков	
  вычисления	
  
матричного	
  умножения	
  и	
  разностного	
  шага	
  
threads	
  
94fc6ee	
  
#include <thread>!
// ... //!
int numThreads;!
desc.add_options()!
("nt", po::value<int>(&numThreads)->default_value(8), "number of worker threads”);!
// ... //!
// Time integration loop!
report.createNewProgress("Time integration");!
while( t < tStop ) { // Time loop!
// Update displacements of kinematically loaded nodes!
// ... //!
auto procFunc = [&](int start, int stop){!
std::unique_ptr<sbfMatrixIterator> iteratorPtr(stiff->createIterator());!
sbfMatrixIterator *iterator = iteratorPtr.get();!
for(int nodeCt = start; nodeCt < stop; nodeCt++) {!
// Make multiplication of stiffness matrix over displacement vector!
iterator->setToRow(nodeCt);!
while(iterator->isValid()) { /* ... */ }!
// Perform finite difference step!
for(int ct = 0; ct < 3; ct++) { /* ... */ }!
}!
};!
std::vector<std::thread> threads; threads.resize(numThreads);!
for(int ct = 0; ct < numThreads; ct++) threads[ct] =!
std::thread( std::bind( procFunc,!
numNodes/numThreads*ct,!
ct != (numThreads-1) ? numNodes/numThreads*(ct+1) : numNodes) );!
for(auto & th : threads) th.join();!
// Make output if required!
// Prepere for next step!
} // End time loop
15	
  
Ветка:	
  
Коммит:	
  
Потоки	
  с	
  оповещениями	
  «начинай»/«сделал»	
  
threads	
  
	
  œb6882	
  
#include <mutex>!
#include <condition_variable>!
// ... //!
struct event{!
std::mutex mtx;!
std::condition_variable cond;!
bool state{false};!
void wait() {!
std::unique_lock<std::mutex> lock(mtx);!
while(!state) cond.wait(lock);!
state = false;!
}!
void set() {!
std::unique_lock<std::mutex> lock(mtx);!
state = true;!
cond.notify_one();!
}!
};!
!
std::vector<event*> eventsStart, eventsStop;!
std::vector<std::thread> threads; threads.resize(numThreads);!
!
auto procFunc = [&](int start, int stop, event *evStart, event *evStop){!
std::unique_ptr<sbfMatrixIterator> iteratorPtr(stiff->createIterator());!
sbfMatrixIterator *iterator = iteratorPtr.get();!
evStop->set();!
while(true){!
evStart->wait();!
for(int nodeCt = start; nodeCt < stop; nodeCt++) {!
// Make multiplication of stiffness matrix over displacement vector!
// Perform finite difference step!
}!
evStop->set();!
}!
}; 16	
  
Ветка:	
  
Коммит:	
  
Потоки	
  с	
  оповещениями	
  «начинай»/«сделал»	
  
threads	
  
	
  œb6882	
  
for(int ct = 0; ct < numThreads; ct++) {!
eventsStart.push_back(new event);!
eventsStop.push_back(new event);!
threads[ct] = std::thread(std::bind(!
procFunc, numNodes/numThreads*ct,!
ct != (numThreads-1) ? numNodes/numThreads*(ct+1) : numNodes,!
eventsStart[ct], eventsStop[ct]));!
threads[ct].detach();!
}!
for(auto ev : eventsStop) ev->wait();!
!
// Time integration loop!
report.createNewProgress("Time integration");!
while( t < tStop ) { // Time loop!
// Update displacements of kinematically loaded nodes!
!
for(auto ev : eventsStart) ev->set();!
for(auto ev : eventsStop) ev->wait();!
!
// Make output if required!
// Prepere for next step!
} // End time loop
17	
  
Ветка:	
  
Коммит:	
  
Параллельное	
  выполнение	
  независимых	
  
секций	
  кода	
  
threads	
  
	
  7f1534d	
  
#include <thread>!
!
sbfMesh *createMesh(int discretParam)!
{!
report("Recreating mesh");!
sbfMesh *mesh = new sbfMesh;!
!
std::unique_ptr<sbfMesh> c(new sbfMesh);!
std::unique_ptr<sbfMesh> plus(new sbfMesh);!
!
auto threadC = std::thread([&](){!
sbfMesh tmp;!
//Construct C letter!
// ... //!
c->addMesh(part4.get());!
});!
!
auto threadPlus = std::thread([&](){!
sbfMesh tmp;!
//Construct plus sign!
// ... //!
plus->translate(2.5, 12.5, 0);!
});!
!
threadC.join();!
threadPlus.join();!
!
// Use of "c" and "plus" to make mesh//!
!
return mesh;!
}
18	
  
MPI	
  
Message	
  Passing	
  Interface	
  (MPI,	
  интерфейс	
  передачи	
  
сообщений)	
  —	
  программный	
  интерфейс	
  для	
  передачи	
  
информации,	
  который	
  позволяет	
  обмениваться	
  сообщениями	
  
между	
  процессами,	
  выполняющими	
  одну	
  задачу.	
  //Wikipedia	
  
MPI_Comm_size	
  (comm,&size)	
  
MPI_Comm_rank	
  (comm,&rank)	
  
	
  
MPI_Send(&buffer,count,type,dest,tag,comm)	
  
MPI_Isend(&buffer,count,type,dest,tag,comm,request)	
  
MPI_Recv(&buffer,count,type,source,tag,comm,status)	
  
MPI_Irecv(&buffer,count,type,source,tag,comm,request)	
  
	
  
MPI_Bcast	
  (&buffer,count,datatype,root,comm)	
  
MPI_Reduce	
  (&sendbuf,&recvbuf,count,datatype,op,root,comm)	
  
MPI_Allreduce	
  (&sendbuf,&recvbuf,count,datatype,op,comm)	
  
	
  
MPI_Barrier	
  (comm)	
  
19	
  
Ветка:	
  
Коммит:	
  
Использование	
  MPI	
  
MPI	
  
b42b24a	
  
CMakeLists.txt!
!
find_package(MPI REQUIRED)!
include_directories(${MPI_INCLUDE_PATH})!
target_link_libraries(${PROJECT_NAME} ${MPI_LIBRARIES})!
set(CMAKE_CXX_COMPILE_FLAGS ${CMAKE_CXX_COMPILE_FLAGS} ${MPI_COMPILE_FLAGS})!
set(CMAKE_CXX_LINK_FLAGS ${CMAKE_CXX_LINK_FLAGS} ${MPI_LINK_FLAGS})!
!
main.cpp!
!
#include <mpi.h>!
// ... //!
MPI_Init(&argc, &argv);!
int procID, numProcs;!
MPI_Comm_size(MPI_COMM_WORLD, &numProcs);!
MPI_Comm_rank(MPI_COMM_WORLD, &procID);!
!
// Create appropriate mesh!
std::unique_ptr<sbfMesh> meshPtr(new sbfMesh);!
if ( procID == 0 ) if( recreateMesh || meshPtr->readMeshFromFiles() ){!
meshPtr.reset(createMesh(discretParam));!
}!
sbfMesh *mesh = meshPtr.get();!
const int numNodes = mesh->numNodes();!
MPI_Bcast(const_cast<int*>(&numNodes), 1, MPI_INT, 0, MPI_COMM_WORLD);!
20	
  
Ветка:	
  
Коммит:	
  
Использование	
  MPI	
  
MPI	
  
	
  b42b24a	
  
// Create and compute stiffness matrix!
std::unique_ptr<sbfStiffMatrixBlock3x3> stiffPtr(new sbfStiffMatrixBlock3x3);!
int numBlocks[2], type;!
if ( procID == 0 ) {!
stiffPtr.reset(createStiffMatrix(mesh, recreateMesh));!
numBlocks[0] = stiffPtr->numBlocks();!
numBlocks[1] = stiffPtr->numBlocksAlter();!
type = static_cast<int>(stiffPtr->type());!
}!
MPI_Bcast(numBlocks, 2, MPI_INT, 0, MPI_COMM_WORLD);!
MPI_Bcast(&type, 1, MPI_INT, 0, MPI_COMM_WORLD);!
if ( procID != 0 ) {!
stiffPtr.reset(new sbfStiffMatrixBlock3x3(numBlocks[0], numNodes, numBlocks[1]));!
stiffPtr->setType(static_cast<MatrixType>(type));!
}!
sbfStiffMatrixBlock3x3 *stiff = stiffPtr.get();!
MPI_Bcast(const_cast<int *>(stiff->indData()), numBlocks[0], MPI_INT, 0, MPI_COMM_WORLD);!
MPI_Bcast(const_cast<int *>(stiff->shiftIndData()), numNodes+1, MPI_INT, 0, MPI_COMM_WORLD);!
if (numBlocks[1]) {!
MPI_Bcast(const_cast<int *>(stiff->indDataAlter()), numBlocks[1], MPI_INT, 0, MPI_COMM_WORLD);!
MPI_Bcast(const_cast<int *>(stiff->shiftIndDataAlter()), numNodes+1, MPI_INT, 0, MPI_COMM_WORLD);!
}!
MPI_Bcast(const_cast<double *>(stiff->data()), numBlocks[0]*9, MPI_DOUBLE, 0, MPI_COMM_WORLD);!
if ( procID != 0 ) stiff->updataAlterPtr();!
!
// ... //!
!
// Fill mass and demping arrays!
if ( procID == 0 ) computeMassDemp(mass, demp, mesh, stiff->propSet(), ksi, recreateMesh);!
MPI_Bcast(mass.data(), numNodes*3, MPI_DOUBLE, 0, MPI_COMM_WORLD);!
MPI_Bcast(demp.data(), numNodes*3, MPI_DOUBLE, 0, MPI_COMM_WORLD);!
21	
  
Ветка:	
  
Коммит:	
  
Использование	
  MPI	
  
MPI	
  
	
  b42b24a	
  
// Time integration loop!
int nodeStart = numNodes/numProcs*procID;!
int nodeStop = procID != numProcs - 1 ? numNodes/numProcs*(procID+1) : numNodes;!
if ( procID == 0 ) report.createNewProgress("Time integration");!
while( t < tStop ) { // Time loop!
// Update displacements of kinematically loaded nodes!
// ... //!
!
MPI_Bcast(displ.data(), numNodes*3, MPI_DOUBLE, 0, MPI_COMM_WORLD);!
rezKU.null();!
reduceBuf.null();!
for(int nodeCt = nodeStart; nodeCt < nodeStop; nodeCt++) {!
// Make multiplication of stiffness matrix over displacement vector!
iterator->setToRow(nodeCt);!
while(iterator->isValid()) { /* ... */ iterator->next(); }!
// Perform finite difference step!
for(int ct = 0; ct < 3; ct++) {!
// ... //!
reduceBuf.data()[3*nodeCt+ct] = temp/(a0*mass.data()[3*nodeCt+ct] + a1*demp.data()[3*nodeCt+ct]);!
}!
}!
MPI_Allreduce(reduceBuf.data(), displ_p1.data(), numNodes*3, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);!
!
// Make output if required!
if ( procID == 0 ) if(t >= tNextOut) { /* ... */ }!
// Prepere for next step!
t += dt;!
displ_m1.copyData(displ); displ.copyData(displ_p1);!
} // End time loop!
if ( procID == 0 ) report.finalizeProgress();!
!
MPI_Finalize();!
22	
  
Ветка:	
  
Коммит:	
  
MPI	
  +	
  потоки	
  
MPI_threads	
  
	
  7b033e3	
  
int nodeStart = numNodes/numProcs*procID;!
int nodeStop = procID != numProcs - 1 ? numNodes/numProcs*(procID+1) : numNodes;!
!
for(int ct = 0; ct < numThreads; ct++) {!
eventsStart.push_back(new event);!
eventsStop.push_back(new event);!
int threadStartNode = nodeStart + (nodeStop - nodeStart)/numThreads*ct;!
int threadStopNode = nodeStart + (nodeStop - nodeStart)/numThreads*(ct+1);!
if(ct == numThreads-1) threadStopNode = nodeStop;!
threads[ct] = std::thread(std::bind(procFunc, threadStartNode, threadStopNode, eventsStart[ct],
eventsStop[ct]));!
threads[ct].detach();!
}!
for(auto ev : eventsStop) ev->wait();!
!
// Time integration loop!
if ( procID == 0 ) report.createNewProgress("Time integration");!
while( t < tStop ) { // Time loop!
// Update displacements of kinematically loaded nodes!
!
MPI_Bcast(displ.data(), numNodes*3, MPI_DOUBLE, 0, MPI_COMM_WORLD);!
rezKU.null(); reduceBuf.null();!
for(auto ev : eventsStart) ev->set();!
for(auto ev : eventsStop) ev->wait();!
MPI_Allreduce(reduceBuf.data(), displ_p1.data(), numNodes*3, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);!
!
// Make output if required!
if ( procID == 0 ) if(t >= tNextOut) { /* ... */}!
// Prepere for next step!
t += dt; displ_m1.copyData(displ); displ.copyData(displ_p1);!
} // End time loop!
if ( procID == 0 ) report.finalizeProgress();
23	
  
Вместо	
  выводов	
  
Один	
  поток	
   openMP	
   threads	
   MPI	
   MPI	
  +	
  
threads	
  
97	
   20	
   21	
   42	
   31	
  
IMHO:	
  
•  При	
  современном	
  развитии	
  вычислительной	
  техники	
  разработчику	
  непростительно	
  
написание	
  не	
  параллельных	
  программ,	
  особенно	
  в	
  области	
  расчетов	
  
•  Современные	
  стандарты	
  и	
  их	
  реализации	
  позволяют	
  относительно	
  быстро	
  
внедрять	
  их	
  в	
  существующие	
  или	
  вновь	
  создаваемые	
  проекты	
  
•  Хотя,	
  возможно	
  в	
  ближайшем	
  будущем	
  компиляторы	
  научатся	
  делать	
  все	
  за	
  нас	
  :)	
  
24	
  
Крутько	
  Евгений	
  
e.s.krutko@gmail.com	
  
google.com/+ЕвгенийКрутько	
  
Репозиторий	
  проекта:	
  
hnps://github.com/eskrut/directIntegra-onSolver.git	
  
25	
  

Contenu connexe

Tendances

Семинар 7. Многопоточное программирование на OpenMP (часть 7)
Семинар 7. Многопоточное программирование на OpenMP (часть 7)Семинар 7. Многопоточное программирование на OpenMP (часть 7)
Семинар 7. Многопоточное программирование на OpenMP (часть 7)Mikhail Kurnosov
 
ПВТ - весна 2015 - Лекция 4. Шаблоны многопоточного программирования
ПВТ - весна 2015 - Лекция 4. Шаблоны многопоточного программированияПВТ - весна 2015 - Лекция 4. Шаблоны многопоточного программирования
ПВТ - весна 2015 - Лекция 4. Шаблоны многопоточного программированияAlexey Paznikov
 
Лекция 3. Виртуальные топологии в MPI. Параллельные алгоритмы в стандарте MPI...
Лекция 3. Виртуальные топологии в MPI. Параллельные алгоритмы в стандарте MPI...Лекция 3. Виртуальные топологии в MPI. Параллельные алгоритмы в стандарте MPI...
Лекция 3. Виртуальные топологии в MPI. Параллельные алгоритмы в стандарте MPI...Alexey Paznikov
 
Семинар 11. Параллельное программирование на MPI (часть 4)
Семинар 11. Параллельное программирование на MPI (часть 4)Семинар 11. Параллельное программирование на MPI (часть 4)
Семинар 11. Параллельное программирование на MPI (часть 4)Mikhail Kurnosov
 
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building BlocksЛекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building BlocksMikhail Kurnosov
 
Векторизация кода (семинар 3)
Векторизация кода (семинар 3)Векторизация кода (семинар 3)
Векторизация кода (семинар 3)Mikhail Kurnosov
 
Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...
Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...
Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...Alexey Paznikov
 
Семинар 6. Многопоточное программирование на OpenMP (часть 6)
Семинар 6. Многопоточное программирование на OpenMP (часть 6)Семинар 6. Многопоточное программирование на OpenMP (часть 6)
Семинар 6. Многопоточное программирование на OpenMP (часть 6)Mikhail Kurnosov
 
Кулагин И.И., Пазников А.А., Курносов М.Г. Оптимизация информационных обменов...
Кулагин И.И., Пазников А.А., Курносов М.Г. Оптимизация информационных обменов...Кулагин И.И., Пазников А.А., Курносов М.Г. Оптимизация информационных обменов...
Кулагин И.И., Пазников А.А., Курносов М.Г. Оптимизация информационных обменов...Alexey Paznikov
 
Семинар 1. Многопоточное программирование на OpenMP (часть 1)
Семинар 1. Многопоточное программирование на OpenMP (часть 1)Семинар 1. Многопоточное программирование на OpenMP (часть 1)
Семинар 1. Многопоточное программирование на OpenMP (часть 1)Mikhail Kurnosov
 
Векторизация кода (семинар 1)
Векторизация кода (семинар 1)Векторизация кода (семинар 1)
Векторизация кода (семинар 1)Mikhail Kurnosov
 
Лекция 7. Стандарт OpenMP (подолжение)
Лекция 7. Стандарт OpenMP (подолжение)Лекция 7. Стандарт OpenMP (подолжение)
Лекция 7. Стандарт OpenMP (подолжение)Mikhail Kurnosov
 
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!Yandex
 
ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...
ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...
ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...Alexey Paznikov
 
JS Fest 2019. Владимир Агафонкин. Быстро по умолчанию: алгоритмическое мышлен...
JS Fest 2019. Владимир Агафонкин. Быстро по умолчанию: алгоритмическое мышлен...JS Fest 2019. Владимир Агафонкин. Быстро по умолчанию: алгоритмическое мышлен...
JS Fest 2019. Владимир Агафонкин. Быстро по умолчанию: алгоритмическое мышлен...JSFestUA
 
ПВТ - весна 2015 - Лекция 3. Реентерабельность. Сигналы. Локальные данные пот...
ПВТ - весна 2015 - Лекция 3. Реентерабельность. Сигналы. Локальные данные пот...ПВТ - весна 2015 - Лекция 3. Реентерабельность. Сигналы. Локальные данные пот...
ПВТ - весна 2015 - Лекция 3. Реентерабельность. Сигналы. Локальные данные пот...Alexey Paznikov
 
ПВТ - весна 2015 - Лекция 2. POSIX Threads. Основные понятия многопоточного п...
ПВТ - весна 2015 - Лекция 2. POSIX Threads. Основные понятия многопоточного п...ПВТ - весна 2015 - Лекция 2. POSIX Threads. Основные понятия многопоточного п...
ПВТ - весна 2015 - Лекция 2. POSIX Threads. Основные понятия многопоточного п...Alexey Paznikov
 
Векторизация кода (семинар 2)
Векторизация кода (семинар 2)Векторизация кода (семинар 2)
Векторизация кода (семинар 2)Mikhail Kurnosov
 
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)Лекция 7: Многопоточное программирование: часть 3 (OpenMP)
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)Mikhail Kurnosov
 
Лекция 4. Производные типы данных в стандарте MPI
Лекция 4. Производные типы данных в стандарте MPIЛекция 4. Производные типы данных в стандарте MPI
Лекция 4. Производные типы данных в стандарте MPIAlexey Paznikov
 

Tendances (20)

Семинар 7. Многопоточное программирование на OpenMP (часть 7)
Семинар 7. Многопоточное программирование на OpenMP (часть 7)Семинар 7. Многопоточное программирование на OpenMP (часть 7)
Семинар 7. Многопоточное программирование на OpenMP (часть 7)
 
ПВТ - весна 2015 - Лекция 4. Шаблоны многопоточного программирования
ПВТ - весна 2015 - Лекция 4. Шаблоны многопоточного программированияПВТ - весна 2015 - Лекция 4. Шаблоны многопоточного программирования
ПВТ - весна 2015 - Лекция 4. Шаблоны многопоточного программирования
 
Лекция 3. Виртуальные топологии в MPI. Параллельные алгоритмы в стандарте MPI...
Лекция 3. Виртуальные топологии в MPI. Параллельные алгоритмы в стандарте MPI...Лекция 3. Виртуальные топологии в MPI. Параллельные алгоритмы в стандарте MPI...
Лекция 3. Виртуальные топологии в MPI. Параллельные алгоритмы в стандарте MPI...
 
Семинар 11. Параллельное программирование на MPI (часть 4)
Семинар 11. Параллельное программирование на MPI (часть 4)Семинар 11. Параллельное программирование на MPI (часть 4)
Семинар 11. Параллельное программирование на MPI (часть 4)
 
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building BlocksЛекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
 
Векторизация кода (семинар 3)
Векторизация кода (семинар 3)Векторизация кода (семинар 3)
Векторизация кода (семинар 3)
 
Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...
Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...
Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...
 
Семинар 6. Многопоточное программирование на OpenMP (часть 6)
Семинар 6. Многопоточное программирование на OpenMP (часть 6)Семинар 6. Многопоточное программирование на OpenMP (часть 6)
Семинар 6. Многопоточное программирование на OpenMP (часть 6)
 
Кулагин И.И., Пазников А.А., Курносов М.Г. Оптимизация информационных обменов...
Кулагин И.И., Пазников А.А., Курносов М.Г. Оптимизация информационных обменов...Кулагин И.И., Пазников А.А., Курносов М.Г. Оптимизация информационных обменов...
Кулагин И.И., Пазников А.А., Курносов М.Г. Оптимизация информационных обменов...
 
Семинар 1. Многопоточное программирование на OpenMP (часть 1)
Семинар 1. Многопоточное программирование на OpenMP (часть 1)Семинар 1. Многопоточное программирование на OpenMP (часть 1)
Семинар 1. Многопоточное программирование на OpenMP (часть 1)
 
Векторизация кода (семинар 1)
Векторизация кода (семинар 1)Векторизация кода (семинар 1)
Векторизация кода (семинар 1)
 
Лекция 7. Стандарт OpenMP (подолжение)
Лекция 7. Стандарт OpenMP (подолжение)Лекция 7. Стандарт OpenMP (подолжение)
Лекция 7. Стандарт OpenMP (подолжение)
 
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
 
ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...
ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...
ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...
 
JS Fest 2019. Владимир Агафонкин. Быстро по умолчанию: алгоритмическое мышлен...
JS Fest 2019. Владимир Агафонкин. Быстро по умолчанию: алгоритмическое мышлен...JS Fest 2019. Владимир Агафонкин. Быстро по умолчанию: алгоритмическое мышлен...
JS Fest 2019. Владимир Агафонкин. Быстро по умолчанию: алгоритмическое мышлен...
 
ПВТ - весна 2015 - Лекция 3. Реентерабельность. Сигналы. Локальные данные пот...
ПВТ - весна 2015 - Лекция 3. Реентерабельность. Сигналы. Локальные данные пот...ПВТ - весна 2015 - Лекция 3. Реентерабельность. Сигналы. Локальные данные пот...
ПВТ - весна 2015 - Лекция 3. Реентерабельность. Сигналы. Локальные данные пот...
 
ПВТ - весна 2015 - Лекция 2. POSIX Threads. Основные понятия многопоточного п...
ПВТ - весна 2015 - Лекция 2. POSIX Threads. Основные понятия многопоточного п...ПВТ - весна 2015 - Лекция 2. POSIX Threads. Основные понятия многопоточного п...
ПВТ - весна 2015 - Лекция 2. POSIX Threads. Основные понятия многопоточного п...
 
Векторизация кода (семинар 2)
Векторизация кода (семинар 2)Векторизация кода (семинар 2)
Векторизация кода (семинар 2)
 
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)Лекция 7: Многопоточное программирование: часть 3 (OpenMP)
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)
 
Лекция 4. Производные типы данных в стандарте MPI
Лекция 4. Производные типы данных в стандарте MPIЛекция 4. Производные типы данных в стандарте MPI
Лекция 4. Производные типы данных в стандарте MPI
 

Similaire à Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повышения производительности численных расчётов

Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)
Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)
Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)Mikhail Kurnosov
 
Опыт разработки статического анализатора кода
Опыт разработки статического анализатора кодаОпыт разработки статического анализатора кода
Опыт разработки статического анализатора кодаAndrey Karpov
 
Netmap (by luigi rizzo) простой и удобный opensource фреймворк для обработк...
Netmap (by luigi rizzo)   простой и удобный opensource фреймворк для обработк...Netmap (by luigi rizzo)   простой и удобный opensource фреймворк для обработк...
Netmap (by luigi rizzo) простой и удобный opensource фреймворк для обработк...Ontico
 
Принципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioПринципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioAndrey Karpov
 
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"Yandex
 
20090720 hpc exercise1
20090720 hpc exercise120090720 hpc exercise1
20090720 hpc exercise1Michael Karpov
 
статический анализ кода
статический анализ кодастатический анализ кода
статический анализ кодаAndrey Karpov
 
Статический анализ кода
Статический анализ кода Статический анализ кода
Статический анализ кода Pavel Tsukanov
 
Tech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVMTech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVMTech Talks @NSU
 
Как приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVMКак приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVMTech Talks @NSU
 
11 встреча — Введение в GPGPU (А. Свириденков)
11 встреча — Введение в GPGPU (А. Свириденков)11 встреча — Введение в GPGPU (А. Свириденков)
11 встреча — Введение в GPGPU (А. Свириденков)Smolensk Computer Science Club
 
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"Fwdays
 
ПВТ - осень 2014 - лекция 1 - Введение в параллельные вычисления
ПВТ - осень 2014 - лекция 1 - Введение в параллельные вычисленияПВТ - осень 2014 - лекция 1 - Введение в параллельные вычисления
ПВТ - осень 2014 - лекция 1 - Введение в параллельные вычисленияAlexey Paznikov
 
20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonovComputer Science Club
 
DSLs in Lisp and Clojure
DSLs in Lisp and ClojureDSLs in Lisp and Clojure
DSLs in Lisp and ClojureVasil Remeniuk
 
Статический анализ Си++ кода
Статический анализ Си++ кодаСтатический анализ Си++ кода
Статический анализ Си++ кодаTatyanazaxarova
 
ADD 2011: Статический анализ Си++ кода
ADD 2011: Статический анализ Си++ кодаADD 2011: Статический анализ Си++ кода
ADD 2011: Статический анализ Си++ кодаAndrey Karpov
 

Similaire à Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повышения производительности численных расчётов (20)

Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)
Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)
Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)
 
Опыт разработки статического анализатора кода
Опыт разработки статического анализатора кодаОпыт разработки статического анализатора кода
Опыт разработки статического анализатора кода
 
Netmap (by luigi rizzo) простой и удобный opensource фреймворк для обработк...
Netmap (by luigi rizzo)   простой и удобный opensource фреймворк для обработк...Netmap (by luigi rizzo)   простой и удобный opensource фреймворк для обработк...
Netmap (by luigi rizzo) простой и удобный opensource фреймворк для обработк...
 
Принципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioПринципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-Studio
 
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
 
20090720 hpc exercise1
20090720 hpc exercise120090720 hpc exercise1
20090720 hpc exercise1
 
статический анализ кода
статический анализ кодастатический анализ кода
статический анализ кода
 
Статический анализ кода
Статический анализ кода Статический анализ кода
Статический анализ кода
 
Tech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVMTech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVM
 
Как приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVMКак приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVM
 
11 встреча — Введение в GPGPU (А. Свириденков)
11 встреча — Введение в GPGPU (А. Свириденков)11 встреча — Введение в GPGPU (А. Свириденков)
11 встреча — Введение в GPGPU (А. Свириденков)
 
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"
 
ПВТ - осень 2014 - лекция 1 - Введение в параллельные вычисления
ПВТ - осень 2014 - лекция 1 - Введение в параллельные вычисленияПВТ - осень 2014 - лекция 1 - Введение в параллельные вычисления
ПВТ - осень 2014 - лекция 1 - Введение в параллельные вычисления
 
Programming c++ (begin-if-else)
Programming c++ (begin-if-else)Programming c++ (begin-if-else)
Programming c++ (begin-if-else)
 
20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov
 
DSLs in Lisp and Clojure
DSLs in Lisp and ClojureDSLs in Lisp and Clojure
DSLs in Lisp and Clojure
 
OpenACC short review
OpenACC short reviewOpenACC short review
OpenACC short review
 
Статический анализ Си++ кода
Статический анализ Си++ кодаСтатический анализ Си++ кода
Статический анализ Си++ кода
 
ADD 2011: Статический анализ Си++ кода
ADD 2011: Статический анализ Си++ кодаADD 2011: Статический анализ Си++ кода
ADD 2011: Статический анализ Си++ кода
 
Erlang
ErlangErlang
Erlang
 

Plus de Yandex

Предсказание оттока игроков из World of Tanks
Предсказание оттока игроков из World of TanksПредсказание оттока игроков из World of Tanks
Предсказание оттока игроков из World of TanksYandex
 
Как принять/организовать работу по поисковой оптимизации сайта, Сергей Царик,...
Как принять/организовать работу по поисковой оптимизации сайта, Сергей Царик,...Как принять/организовать работу по поисковой оптимизации сайта, Сергей Царик,...
Как принять/организовать работу по поисковой оптимизации сайта, Сергей Царик,...Yandex
 
Структурированные данные, Юлия Тихоход, лекция в Школе вебмастеров Яндекса
Структурированные данные, Юлия Тихоход, лекция в Школе вебмастеров ЯндексаСтруктурированные данные, Юлия Тихоход, лекция в Школе вебмастеров Яндекса
Структурированные данные, Юлия Тихоход, лекция в Школе вебмастеров ЯндексаYandex
 
Представление сайта в поиске, Сергей Лысенко, лекция в Школе вебмастеров Яндекса
Представление сайта в поиске, Сергей Лысенко, лекция в Школе вебмастеров ЯндексаПредставление сайта в поиске, Сергей Лысенко, лекция в Школе вебмастеров Яндекса
Представление сайта в поиске, Сергей Лысенко, лекция в Школе вебмастеров ЯндексаYandex
 
Плохие методы продвижения сайта, Екатерины Гладких, лекция в Школе вебмастеро...
Плохие методы продвижения сайта, Екатерины Гладких, лекция в Школе вебмастеро...Плохие методы продвижения сайта, Екатерины Гладких, лекция в Школе вебмастеро...
Плохие методы продвижения сайта, Екатерины Гладких, лекция в Школе вебмастеро...Yandex
 
Основные принципы ранжирования, Сергей Царик и Антон Роменский, лекция в Школ...
Основные принципы ранжирования, Сергей Царик и Антон Роменский, лекция в Школ...Основные принципы ранжирования, Сергей Царик и Антон Роменский, лекция в Школ...
Основные принципы ранжирования, Сергей Царик и Антон Роменский, лекция в Школ...Yandex
 
Основные принципы индексирования сайта, Александр Смирнов, лекция в Школе веб...
Основные принципы индексирования сайта, Александр Смирнов, лекция в Школе веб...Основные принципы индексирования сайта, Александр Смирнов, лекция в Школе веб...
Основные принципы индексирования сайта, Александр Смирнов, лекция в Школе веб...Yandex
 
Мобильное приложение: как и зачем, Александр Лукин, лекция в Школе вебмастеро...
Мобильное приложение: как и зачем, Александр Лукин, лекция в Школе вебмастеро...Мобильное приложение: как и зачем, Александр Лукин, лекция в Школе вебмастеро...
Мобильное приложение: как и зачем, Александр Лукин, лекция в Школе вебмастеро...Yandex
 
Сайты на мобильных устройствах, Олег Ножичкин, лекция в Школе вебмастеров Янд...
Сайты на мобильных устройствах, Олег Ножичкин, лекция в Школе вебмастеров Янд...Сайты на мобильных устройствах, Олег Ножичкин, лекция в Школе вебмастеров Янд...
Сайты на мобильных устройствах, Олег Ножичкин, лекция в Школе вебмастеров Янд...Yandex
 
Качественная аналитика сайта, Юрий Батиевский, лекция в Школе вебмастеров Янд...
Качественная аналитика сайта, Юрий Батиевский, лекция в Школе вебмастеров Янд...Качественная аналитика сайта, Юрий Батиевский, лекция в Школе вебмастеров Янд...
Качественная аналитика сайта, Юрий Батиевский, лекция в Школе вебмастеров Янд...Yandex
 
Что можно и что нужно измерять на сайте, Петр Аброськин, лекция в Школе вебма...
Что можно и что нужно измерять на сайте, Петр Аброськин, лекция в Школе вебма...Что можно и что нужно измерять на сайте, Петр Аброськин, лекция в Школе вебма...
Что можно и что нужно измерять на сайте, Петр Аброськин, лекция в Школе вебма...Yandex
 
Как правильно поставить ТЗ на создание сайта, Алексей Бородкин, лекция в Школ...
Как правильно поставить ТЗ на создание сайта, Алексей Бородкин, лекция в Школ...Как правильно поставить ТЗ на создание сайта, Алексей Бородкин, лекция в Школ...
Как правильно поставить ТЗ на создание сайта, Алексей Бородкин, лекция в Школ...Yandex
 
Как защитить свой сайт, Пётр Волков, лекция в Школе вебмастеров
Как защитить свой сайт, Пётр Волков, лекция в Школе вебмастеровКак защитить свой сайт, Пётр Волков, лекция в Школе вебмастеров
Как защитить свой сайт, Пётр Волков, лекция в Школе вебмастеровYandex
 
Как правильно составить структуру сайта, Дмитрий Сатин, лекция в Школе вебмас...
Как правильно составить структуру сайта, Дмитрий Сатин, лекция в Школе вебмас...Как правильно составить структуру сайта, Дмитрий Сатин, лекция в Школе вебмас...
Как правильно составить структуру сайта, Дмитрий Сатин, лекция в Школе вебмас...Yandex
 
Технические особенности создания сайта, Дмитрий Васильева, лекция в Школе веб...
Технические особенности создания сайта, Дмитрий Васильева, лекция в Школе веб...Технические особенности создания сайта, Дмитрий Васильева, лекция в Школе веб...
Технические особенности создания сайта, Дмитрий Васильева, лекция в Школе веб...Yandex
 
Конструкторы для отдельных элементов сайта, Елена Першина, лекция в Школе веб...
Конструкторы для отдельных элементов сайта, Елена Першина, лекция в Школе веб...Конструкторы для отдельных элементов сайта, Елена Першина, лекция в Школе веб...
Конструкторы для отдельных элементов сайта, Елена Першина, лекция в Школе веб...Yandex
 
Контент для интернет-магазинов, Катерина Ерошина, лекция в Школе вебмастеров ...
Контент для интернет-магазинов, Катерина Ерошина, лекция в Школе вебмастеров ...Контент для интернет-магазинов, Катерина Ерошина, лекция в Школе вебмастеров ...
Контент для интернет-магазинов, Катерина Ерошина, лекция в Школе вебмастеров ...Yandex
 
Как написать хороший текст для сайта, Катерина Ерошина, лекция в Школе вебмас...
Как написать хороший текст для сайта, Катерина Ерошина, лекция в Школе вебмас...Как написать хороший текст для сайта, Катерина Ерошина, лекция в Школе вебмас...
Как написать хороший текст для сайта, Катерина Ерошина, лекция в Школе вебмас...Yandex
 
Usability и дизайн - как не помешать пользователю, Алексей Иванов, лекция в Ш...
Usability и дизайн - как не помешать пользователю, Алексей Иванов, лекция в Ш...Usability и дизайн - как не помешать пользователю, Алексей Иванов, лекция в Ш...
Usability и дизайн - как не помешать пользователю, Алексей Иванов, лекция в Ш...Yandex
 
Cайт. Зачем он и каким должен быть, Алексей Иванов, лекция в Школе вебмастеро...
Cайт. Зачем он и каким должен быть, Алексей Иванов, лекция в Школе вебмастеро...Cайт. Зачем он и каким должен быть, Алексей Иванов, лекция в Школе вебмастеро...
Cайт. Зачем он и каким должен быть, Алексей Иванов, лекция в Школе вебмастеро...Yandex
 

Plus de Yandex (20)

Предсказание оттока игроков из World of Tanks
Предсказание оттока игроков из World of TanksПредсказание оттока игроков из World of Tanks
Предсказание оттока игроков из World of Tanks
 
Как принять/организовать работу по поисковой оптимизации сайта, Сергей Царик,...
Как принять/организовать работу по поисковой оптимизации сайта, Сергей Царик,...Как принять/организовать работу по поисковой оптимизации сайта, Сергей Царик,...
Как принять/организовать работу по поисковой оптимизации сайта, Сергей Царик,...
 
Структурированные данные, Юлия Тихоход, лекция в Школе вебмастеров Яндекса
Структурированные данные, Юлия Тихоход, лекция в Школе вебмастеров ЯндексаСтруктурированные данные, Юлия Тихоход, лекция в Школе вебмастеров Яндекса
Структурированные данные, Юлия Тихоход, лекция в Школе вебмастеров Яндекса
 
Представление сайта в поиске, Сергей Лысенко, лекция в Школе вебмастеров Яндекса
Представление сайта в поиске, Сергей Лысенко, лекция в Школе вебмастеров ЯндексаПредставление сайта в поиске, Сергей Лысенко, лекция в Школе вебмастеров Яндекса
Представление сайта в поиске, Сергей Лысенко, лекция в Школе вебмастеров Яндекса
 
Плохие методы продвижения сайта, Екатерины Гладких, лекция в Школе вебмастеро...
Плохие методы продвижения сайта, Екатерины Гладких, лекция в Школе вебмастеро...Плохие методы продвижения сайта, Екатерины Гладких, лекция в Школе вебмастеро...
Плохие методы продвижения сайта, Екатерины Гладких, лекция в Школе вебмастеро...
 
Основные принципы ранжирования, Сергей Царик и Антон Роменский, лекция в Школ...
Основные принципы ранжирования, Сергей Царик и Антон Роменский, лекция в Школ...Основные принципы ранжирования, Сергей Царик и Антон Роменский, лекция в Школ...
Основные принципы ранжирования, Сергей Царик и Антон Роменский, лекция в Школ...
 
Основные принципы индексирования сайта, Александр Смирнов, лекция в Школе веб...
Основные принципы индексирования сайта, Александр Смирнов, лекция в Школе веб...Основные принципы индексирования сайта, Александр Смирнов, лекция в Школе веб...
Основные принципы индексирования сайта, Александр Смирнов, лекция в Школе веб...
 
Мобильное приложение: как и зачем, Александр Лукин, лекция в Школе вебмастеро...
Мобильное приложение: как и зачем, Александр Лукин, лекция в Школе вебмастеро...Мобильное приложение: как и зачем, Александр Лукин, лекция в Школе вебмастеро...
Мобильное приложение: как и зачем, Александр Лукин, лекция в Школе вебмастеро...
 
Сайты на мобильных устройствах, Олег Ножичкин, лекция в Школе вебмастеров Янд...
Сайты на мобильных устройствах, Олег Ножичкин, лекция в Школе вебмастеров Янд...Сайты на мобильных устройствах, Олег Ножичкин, лекция в Школе вебмастеров Янд...
Сайты на мобильных устройствах, Олег Ножичкин, лекция в Школе вебмастеров Янд...
 
Качественная аналитика сайта, Юрий Батиевский, лекция в Школе вебмастеров Янд...
Качественная аналитика сайта, Юрий Батиевский, лекция в Школе вебмастеров Янд...Качественная аналитика сайта, Юрий Батиевский, лекция в Школе вебмастеров Янд...
Качественная аналитика сайта, Юрий Батиевский, лекция в Школе вебмастеров Янд...
 
Что можно и что нужно измерять на сайте, Петр Аброськин, лекция в Школе вебма...
Что можно и что нужно измерять на сайте, Петр Аброськин, лекция в Школе вебма...Что можно и что нужно измерять на сайте, Петр Аброськин, лекция в Школе вебма...
Что можно и что нужно измерять на сайте, Петр Аброськин, лекция в Школе вебма...
 
Как правильно поставить ТЗ на создание сайта, Алексей Бородкин, лекция в Школ...
Как правильно поставить ТЗ на создание сайта, Алексей Бородкин, лекция в Школ...Как правильно поставить ТЗ на создание сайта, Алексей Бородкин, лекция в Школ...
Как правильно поставить ТЗ на создание сайта, Алексей Бородкин, лекция в Школ...
 
Как защитить свой сайт, Пётр Волков, лекция в Школе вебмастеров
Как защитить свой сайт, Пётр Волков, лекция в Школе вебмастеровКак защитить свой сайт, Пётр Волков, лекция в Школе вебмастеров
Как защитить свой сайт, Пётр Волков, лекция в Школе вебмастеров
 
Как правильно составить структуру сайта, Дмитрий Сатин, лекция в Школе вебмас...
Как правильно составить структуру сайта, Дмитрий Сатин, лекция в Школе вебмас...Как правильно составить структуру сайта, Дмитрий Сатин, лекция в Школе вебмас...
Как правильно составить структуру сайта, Дмитрий Сатин, лекция в Школе вебмас...
 
Технические особенности создания сайта, Дмитрий Васильева, лекция в Школе веб...
Технические особенности создания сайта, Дмитрий Васильева, лекция в Школе веб...Технические особенности создания сайта, Дмитрий Васильева, лекция в Школе веб...
Технические особенности создания сайта, Дмитрий Васильева, лекция в Школе веб...
 
Конструкторы для отдельных элементов сайта, Елена Першина, лекция в Школе веб...
Конструкторы для отдельных элементов сайта, Елена Першина, лекция в Школе веб...Конструкторы для отдельных элементов сайта, Елена Першина, лекция в Школе веб...
Конструкторы для отдельных элементов сайта, Елена Першина, лекция в Школе веб...
 
Контент для интернет-магазинов, Катерина Ерошина, лекция в Школе вебмастеров ...
Контент для интернет-магазинов, Катерина Ерошина, лекция в Школе вебмастеров ...Контент для интернет-магазинов, Катерина Ерошина, лекция в Школе вебмастеров ...
Контент для интернет-магазинов, Катерина Ерошина, лекция в Школе вебмастеров ...
 
Как написать хороший текст для сайта, Катерина Ерошина, лекция в Школе вебмас...
Как написать хороший текст для сайта, Катерина Ерошина, лекция в Школе вебмас...Как написать хороший текст для сайта, Катерина Ерошина, лекция в Школе вебмас...
Как написать хороший текст для сайта, Катерина Ерошина, лекция в Школе вебмас...
 
Usability и дизайн - как не помешать пользователю, Алексей Иванов, лекция в Ш...
Usability и дизайн - как не помешать пользователю, Алексей Иванов, лекция в Ш...Usability и дизайн - как не помешать пользователю, Алексей Иванов, лекция в Ш...
Usability и дизайн - как не помешать пользователю, Алексей Иванов, лекция в Ш...
 
Cайт. Зачем он и каким должен быть, Алексей Иванов, лекция в Школе вебмастеро...
Cайт. Зачем он и каким должен быть, Алексей Иванов, лекция в Школе вебмастеро...Cайт. Зачем он и каким должен быть, Алексей Иванов, лекция в Школе вебмастеро...
Cайт. Зачем он и каким должен быть, Алексей Иванов, лекция в Школе вебмастеро...
 

Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повышения производительности численных расчётов

  • 1. C++  User  Group  Mee-ng,  Nizhniy  Novgorod,  19.04.14   Опыт  внедрения  технологий  параллельных  вычислений   для  повышения  производительности  численных  расчетов   Крутько  Е.С.   НИЦ  «Курчатовский  институт»   e.s.krutko@gmail.com  
  • 2. План  презентации   •  Рассмотрение  кода  программы  моделирования  динамики   твердого  тела  по  методу  конечных  элементов   •  Использование  openmp   •  Явное  создание  вычислительных  потоков   •  Использование  MPI   •  Комбинированный  подход   Репозиторий  проекта:   hnps://github.com/eskrut/directIntegra-onSolver.git   2  
  • 3. Кратко  о  теории   M¨q + C ˙q + Kq = f q = {dx0, dy0, dz0, · · · dxN 1, dyN 1, dzN 1}T M = 0 B B B @ m0 0 0 0 0 m1 0 0 0 0 ... 0 0 0 0 mN 1 1 C C C A C = ⇠M ˙q = qt+ t qt t 2 t , ¨q = qt+ t 2qt + qt t 2 t qt+ t(a0M + a1C) = f Kq + a2Mqt (a0M a1C)qt t Задача   решается   по   методу   к о н е ч н ы х   э л е м е н т о в   с   использованием   явной   схемы   интегрирования   по   времени.   Вся   необходимая   логика   МКЭ   реализована   во   внешней   библиотеке,  необходимо  только   построить   на   ее   основе   решатель.   3  
  • 4. Объект  исследования   ~250  000    узлов   4  
  • 5. Ветка:   Коммит:   Основной  код  программы   master   9f49d14   int main(int argc, char ** argv)! {! int discretParam, numOutput;! double t, tStop, dt, dtOut, tNextOut, transT;! double ampX, freqX, ksi;! bool recreateMesh = false;! bool makeNodesRenumbering = true;! po::options_description desc("Program options");! desc.add_options()! ("help,h", "print help message")! ("dt", po::value<double>(&dt)->default_value(1e-5), "integration time step")! ("tStop,t", po::value<double>(&tStop)->default_value(1e1), "time range")! ("transT", po::value<double>(&transT)->default_value(1e-3), "load transition time")! ("ampX,a", po::value<double>(&ampX)->default_value(1e-3), "displacement amplitude")! ("freqX,f", po::value<double>(&freqX)->default_value(1e0), "displacement frequency [Hz]")! ("ksi,k", po::value<double>(&ksi)->default_value(1e-1), "damping factor")! ("numOutput,n", po::value<int>(&numOutput)->default_value(500), "number of outputs")! ("discretParam,d", po::value<int>(&discretParam)->default_value(2), "discretisation parameter")! ("recreateMesh,m", "recreate mesh")! ("no-nr", "do not optimize nodes numbering")! ;! po::variables_map vm;! po::store(po::parse_command_line(argc, argv, desc), vm);! po::notify(vm);! if (vm.count("help") || vm.count("h")) { std::cout << desc << "n"; return 1; }! if (vm.count("recreateMesh") || vm.count("m")) { recreateMesh = true; }! if (vm.count("no-nr")) { makeNodesRenumbering = false; }! ! t = tNextOut = 0;! dtOut = tStop/numOutput;! double a0, a1, a2;! a0 = 1.0/(dt*dt); a1 = 1.0/(2.0*dt); a2 = 2.0*a0; 5  
  • 6. Ветка:   Коммит:   Основной  код  программы   master   9f49d14   // Create appropriate mesh! std::unique_ptr<sbfMesh> meshPtr(new sbfMesh);! if( recreateMesh || meshPtr->readMeshFromFiles() ){! meshPtr.reset(createMesh(discretParam));! if ( makeNodesRenumbering ) meshPtr->optimizeNodesNumbering();! meshPtr->writeMeshToFiles();! }! sbfMesh *mesh = meshPtr.get();! const int numNodes = mesh->numNodes();! ! // Create and compute stiffness matrix! std::unique_ptr<sbfStiffMatrixBlock3x3> stiffPtr(createStiffMatrix(mesh, recreateMesh));! sbfStiffMatrixBlock3x3 *stiff = stiffPtr.get();! ! // Create nodes data storages! NodesData<double, 3> displ_m1(mesh), displ("displ", mesh), displ_p1(mesh);! NodesData<double, 3> force(mesh), mass("mass", mesh), demp(mesh), rezKU(mesh);! mass.null(); force.null(); demp.null(); displ_m1.null(); displ.null();! ! // Fill mass and demping arrays! computeMassDemp(mass, demp, mesh, stiff->propSet(), ksi, recreateMesh);! ! // Get indexes of kinematic loaded nodes! std::vector<int> loadedNodesDown, loadedNodesUp;! double maxY = mesh->maxY();! for(int ct = 0; ct < numNodes; ct++){! if( std::fabs(mesh->node(ct).y()) < 1e-5) loadedNodesDown.push_back(ct);! if( std::fabs(mesh->node(ct).y() - maxY) < 1e-5 ) loadedNodesUp.push_back(ct);! }! const int numLDown = loadedNodesDown.size(), numLUp = loadedNodesUp.size();! ! // Stiffness matrix iteration halper! std::unique_ptr<sbfMatrixIterator> iteratorPtr(stiff->createIterator());! sbfMatrixIterator *iterator = iteratorPtr.get(); 6  
  • 7. Ветка:   Коммит:   Основной  код  программы   master   9f49d14   // Time integration loop! report.createNewProgress("Time integration");! while( t < tStop ) { // Time loop! // Update displacements of kinematically loaded nodes! double tmp[3], temp; getDispl(t, tmp, ampX, freqX, transT);! for(int nodeCt = 0; nodeCt < numLDown; ++nodeCt) for(int ct = 0; ct < 3; ct++)! displ.data(loadedNodesDown[nodeCt], ct) = tmp[ct];! for(int nodeCt = 0; nodeCt < numLUp; ++nodeCt) for(int ct = 0; ct < 3; ct++)! displ.data(loadedNodesUp[nodeCt], ct) = tmp[ct]/3;! ! for(int nodeCt = 0; nodeCt < numNodes; nodeCt++) {! // Make multiplication of stiffness matrix over displacement vector! iterator->setToRow(nodeCt);! double *rez = rezKU.data() + nodeCt*3;! rez[0] = rez[1] = rez[2] = 0.0;! while(iterator->isValid()) {! int columnID = iterator->column();! double *vectPart = displ.data() + columnID*3;! double *block = iterator->data();! for(int rowCt = 0; rowCt < 3; ++rowCt)! for(int colCt = 0; colCt < 3; ++colCt)! rez[rowCt] += block[rowCt*3+colCt]*vectPart[colCt];! iterator->next();! }! // Perform finite difference step! for(int ct = 0; ct < 3; ct++) {! temp=force.data(nodeCt, ct) - rezKU.data(nodeCt, ct) +! a2*mass.data(nodeCt, ct)*displ.data(nodeCt, ct) -! (a0*mass.data(nodeCt, ct) - a1*demp.data(nodeCt, ct))*displ_m1.data(nodeCt, ct);! displ_p1.data(nodeCt, ct) = temp/(a0*mass.data(nodeCt, ct) + a1*demp.data(nodeCt, ct));! }! }! // Make output if required! if(t >= tNextOut) { displ.writeToFile();tNextOut += dtOut;report.updateProgress(t/tStop*100);}! // Prepere for next step! t += dt;! displ_m1.copyData(displ); displ.copyData(displ_p1);! } // End time loop! report.finalizeProgress();! return 0; 7  
  • 8. Ветка:   Коммит:   Поиск  узкого  места   master   6d51e09   // Time integration loop! report.createNewProgress("Time integration");! std::chrono::nanoseconds period1(0), period2(0), period3(0), period4(0);! while( t < tStop ) { // Time loop! auto timePoint_0 = Clock::now();! // Update displacements of kinematically loaded nodes! // .... //! auto timePoint_1 = Clock::now();! for(int nodeCt = 0; nodeCt < numNodes; nodeCt++) {! // Make multiplication of stiffness matrix over displacement vector! // .... //! }! auto timePoint_2 = Clock::now();! for(int nodeCt = 0; nodeCt < numNodes; nodeCt++) {! // Perform finite difference step! // .... //! }! auto timePoint_3 = Clock::now();! // Make output if required! // Prepere for next step! // .... //! auto timePoint_4 = Clock::now();! period1 += std::chrono::duration_cast<std::chrono::nanoseconds>(timePoint_1 - timePoint_0);! period2 += std::chrono::duration_cast<std::chrono::nanoseconds>(timePoint_2 - timePoint_1);! period3 += std::chrono::duration_cast<std::chrono::nanoseconds>(timePoint_3 - timePoint_2);! period4 += std::chrono::duration_cast<std::chrono::nanoseconds>(timePoint_4 - timePoint_3);! } // End time loop! report.finalizeProgress();! ! report("Prepare part time : ", period1.count());! report("Matrix multiplication time : ", period2.count());! report("Finite difference step time : ", period3.count());! report("Finilizing part time : ", period4.count());! ! Вывод: Prepare part time : 26608769! Matrix multiplication time : 87985118534! Finite difference step time : 7031352999! Finilizing part time : 2039084873! 8  
  • 9. OpenMP   OpenMP   (Open   Mul--­‐Processing)   —   открытый   стандарт   для   распараллеливания   программ   на   языках   Си,   Си++   и   Фортран.   Описывает   совокупность   директив   компилятора,   библиотечных   процедур   и   переменных   окружения,   которые   предназначены   для   программирования   многопоточных   приложений   на   многопроцессорных  системах  с  общей  памятью  //Wikipedia   #pragma  omp  parallel   #pragma  omp  for   #pragma  omp  sec-ons   #pragma  omp  single   #pragma  omp  parallel  for   #pragma  omp  parallel  sec-ons   #pragma  omp  task   #pragma  omp  master   #pragma  omp  cri-cal   #pragma  omp  barrier     void  omp_set_num_threads(int  );   int  omp_get_num_threads(void);   int  omp_get_max_threads(void);   int  omp_get_thread_num(void);   int  omp_get_num_procs(void);   int  omp_in_parallel(void);   void  omp_set_dynamic(int  );   void  omp_set_lock(omp_lock_t  *);   int  omp_test_lock(omp_lock_t  *);       OMP_SCHEDULE  type[,chunk]   OMP_NUM_THREADS  num   OMP_DYNAMIC  dynamic   OMP_NESTED  nested   OMP_STACKSIZE  size   OMP_WAIT_POLICY  policy   OMP_MAX_ACTIVE_LEVELS  levels   OMP_THREAD_LIMIT  limit   9  
  • 10. Ветка:   Коммит:   Первая  попытка  с  openMP  (не  работает)   openMP   99940bc   CMakeLists.txt! ! find_package(OpenMP REQUIRED)! set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")! ! main.cpp! ! #include <omp.h>! // ... //! // Stiffness matrix iteration halper! std::unique_ptr<sbfMatrixIterator> iteratorPtr(stiff->createIterator());! sbfMatrixIterator *iterator = iteratorPtr.get();! ! // Time integration loop! report.createNewProgress("Time integration");! while( t < tStop ) { // Time loop! // Update displacements of kinematically loaded nodes! // ... //! #pragma omp parallel for! for(int nodeCt = 0; nodeCt < numNodes; nodeCt++) {! // Make multiplication of stiffness matrix over displacement vector! iterator->setToRow(nodeCt);! // ... //! while(iterator->isValid()) {! // ... //! iterator->next();! }! // Perform finite difference step! for(int ct = 0; ct < 3; ct++) {! temp=force.data(nodeCt, ct) // ... //;! displ_p1.data(nodeCt, ct) = temp/(a0*mass.data(nodeCt, ct)// ... //);! }! }! // Make output if required! // Prepere for next step! } // End time loop 10  
  • 11. Ветка:   Коммит:   Нормальная  работа  openMP   openMP    3f10371   // Time integration loop! report.createNewProgress("Time integration");! while( t < tStop ) { // Time loop! double tmp[3], temp;! // Update displacements of kinematically loaded nodes! // ... //! #pragma omp parallel private(temp)! {! // Stiffness matrix iteration halper! std::unique_ptr<sbfMatrixIterator> iteratorPtr(stiff->createIterator());! sbfMatrixIterator *iterator = iteratorPtr.get();! #pragma omp for! for(int nodeCt = 0; nodeCt < numNodes; nodeCt++) {! // Make multiplication of stiffness matrix over displacement vector! iterator->setToRow(nodeCt);! // ... //! while(iterator->isValid()) {! // ... //! iterator->next();! }! // Perform finite difference step! for(int ct = 0; ct < 3; ct++) {! temp=force.data(nodeCt, ct) - rezKU.data(nodeCt, ct) +! a2*mass.data(nodeCt, ct)*displ.data(nodeCt, ct) -! (a0*mass.data(nodeCt, ct) - a1*demp.data(nodeCt, ct))*displ_m1.data(nodeCt, ct);! displ_p1.data(nodeCt, ct) = temp/(a0*mass.data(nodeCt, ct) + a1*demp.data(nodeCt, ct));! }! }//End of #pragma omp for! }//End of #pragma omp parallel! // Make output if required! // Prepere for next step! } // End time loop 11  
  • 12. Ветка:   Коммит:   Реорганизация  области  параллельности   openMP    4579611   // Time integration loop! double tmp[3];! #pragma omp parallel! {! // Stiffness matrix iteration halper! std::unique_ptr<sbfMatrixIterator> iteratorPtr(stiff->createIterator());! sbfMatrixIterator *iterator = iteratorPtr.get();! while( t < tStop ) { // Time loop! // Update displacements of kinematically loaded nodes! #pragma omp master! getDispl(t, tmp, ampX, freqX, transT);! #pragma omp for nowait! for(int nodeCt = 0; nodeCt < numLDown; ++nodeCt) for(int ct = 0; ct < 3; ct++)! displ.data(loadedNodesDown[nodeCt], ct) = tmp[ct];! #pragma omp for! for(int nodeCt = 0; nodeCt < numLUp; ++nodeCt) for(int ct = 0; ct < 3; ct++)! displ.data(loadedNodesUp[nodeCt], ct) = tmp[ct]/3;! #pragma omp for! for(int nodeCt = 0; nodeCt < numNodes; nodeCt++) {! // Make multiplication of stiffness matrix over displacement vector! iterator->setToRow(nodeCt);! // ... //! while(iterator->isValid()) {! // ... //! iterator->next();! }! // Perform finite difference step! for(int ct = 0; ct < 3; ct++)! // ... //! }//End of #pragma omp for! #pragma omp master! {// Make output if required! t += dt;}//End of #pragma omp master! #pragma omp for! for(int nodeCt = 0; nodeCt < numNodes; nodeCt++) {! // Prepere for next step! for(int ct = 0; ct < 3; ct++) {! displ_m1.data()[3*nodeCt+ct] = displ.data()[3*nodeCt+ct];}! }//End of #pragma omp for! } // End time loop! }//End of #pragma omp parallel 12  
  • 13. Ветка:   Коммит:   Параллельное  выполнение  секций  кода   openMP    84f7a19   sbfMesh *mesh = new sbfMesh, tmp;! std::unique_ptr<sbfMesh> c(new sbfMesh);! std::unique_ptr<sbfMesh> plus(new sbfMesh);! #pragma omp parallel sections private(tmp)! {! #pragma omp section! {! //Construct C letter! std::unique_ptr<sbfMesh> roundInner(sbfMesh::makeCylinderPart(1,2,0,2*std::atan(1),0,1,d,2*d,d));! std::unique_ptr<sbfMesh> roundOuter(sbfMesh::makeCylinderPart(5,6,0,2*std::atan(1),0,1,d,8*d,d));! std::unique_ptr<sbfMesh> round(new sbfMesh);! round->addMesh(roundInner.get());! round->addMesh(roundOuter.get());! std::unique_ptr<sbfMesh> part0(sbfMesh::makeBlock(4, 1, 1, 4*d, d, d));! std::unique_ptr<sbfMesh> part4(sbfMesh::makeBlock(3, 1, 1, 3*d, d, d));! part0->translate(0, 4, 0);! c->addMesh(part0.get());! tmp = *round.get();! tmp.translate(4, 19, 0);! c->addMesh(tmp);! // ... ///! }//End of #pragma omp section! ! #pragma omp section! {! //Construct plus sign! std::unique_ptr<sbfMesh> part10(sbfMesh::makeBlock(11, 1, 1, 11*d, d, d));! std::unique_ptr<sbfMesh> part11(sbfMesh::makeBlock(1, 3, 1, d, 3*d, d));! std::unique_ptr<sbfMesh> part12(sbfMesh::makeBlock(10, 1, 1, 10*d, d, d));! part11->translate(0, 1, 0);! part12->translate(0, 4, 0);! tmp = *part10.get();! // ... //! }//End of #pragma omp section! }//End of#pragma omp parallel sections private(tmp) 13  
  • 14. Явное  создание  отдельных  вычислительных  потоков   Основные  инструменты  работы  с  потоками:   •  POSIX  /  WinAPI   •  boost::thread   •  std::thread   14  
  • 15. Ветка:   Коммит:   Создание  новых  потоков  вычисления   матричного  умножения  и  разностного  шага   threads   94fc6ee   #include <thread>! // ... //! int numThreads;! desc.add_options()! ("nt", po::value<int>(&numThreads)->default_value(8), "number of worker threads”);! // ... //! // Time integration loop! report.createNewProgress("Time integration");! while( t < tStop ) { // Time loop! // Update displacements of kinematically loaded nodes! // ... //! auto procFunc = [&](int start, int stop){! std::unique_ptr<sbfMatrixIterator> iteratorPtr(stiff->createIterator());! sbfMatrixIterator *iterator = iteratorPtr.get();! for(int nodeCt = start; nodeCt < stop; nodeCt++) {! // Make multiplication of stiffness matrix over displacement vector! iterator->setToRow(nodeCt);! while(iterator->isValid()) { /* ... */ }! // Perform finite difference step! for(int ct = 0; ct < 3; ct++) { /* ... */ }! }! };! std::vector<std::thread> threads; threads.resize(numThreads);! for(int ct = 0; ct < numThreads; ct++) threads[ct] =! std::thread( std::bind( procFunc,! numNodes/numThreads*ct,! ct != (numThreads-1) ? numNodes/numThreads*(ct+1) : numNodes) );! for(auto & th : threads) th.join();! // Make output if required! // Prepere for next step! } // End time loop 15  
  • 16. Ветка:   Коммит:   Потоки  с  оповещениями  «начинай»/«сделал»   threads    œb6882   #include <mutex>! #include <condition_variable>! // ... //! struct event{! std::mutex mtx;! std::condition_variable cond;! bool state{false};! void wait() {! std::unique_lock<std::mutex> lock(mtx);! while(!state) cond.wait(lock);! state = false;! }! void set() {! std::unique_lock<std::mutex> lock(mtx);! state = true;! cond.notify_one();! }! };! ! std::vector<event*> eventsStart, eventsStop;! std::vector<std::thread> threads; threads.resize(numThreads);! ! auto procFunc = [&](int start, int stop, event *evStart, event *evStop){! std::unique_ptr<sbfMatrixIterator> iteratorPtr(stiff->createIterator());! sbfMatrixIterator *iterator = iteratorPtr.get();! evStop->set();! while(true){! evStart->wait();! for(int nodeCt = start; nodeCt < stop; nodeCt++) {! // Make multiplication of stiffness matrix over displacement vector! // Perform finite difference step! }! evStop->set();! }! }; 16  
  • 17. Ветка:   Коммит:   Потоки  с  оповещениями  «начинай»/«сделал»   threads    œb6882   for(int ct = 0; ct < numThreads; ct++) {! eventsStart.push_back(new event);! eventsStop.push_back(new event);! threads[ct] = std::thread(std::bind(! procFunc, numNodes/numThreads*ct,! ct != (numThreads-1) ? numNodes/numThreads*(ct+1) : numNodes,! eventsStart[ct], eventsStop[ct]));! threads[ct].detach();! }! for(auto ev : eventsStop) ev->wait();! ! // Time integration loop! report.createNewProgress("Time integration");! while( t < tStop ) { // Time loop! // Update displacements of kinematically loaded nodes! ! for(auto ev : eventsStart) ev->set();! for(auto ev : eventsStop) ev->wait();! ! // Make output if required! // Prepere for next step! } // End time loop 17  
  • 18. Ветка:   Коммит:   Параллельное  выполнение  независимых   секций  кода   threads    7f1534d   #include <thread>! ! sbfMesh *createMesh(int discretParam)! {! report("Recreating mesh");! sbfMesh *mesh = new sbfMesh;! ! std::unique_ptr<sbfMesh> c(new sbfMesh);! std::unique_ptr<sbfMesh> plus(new sbfMesh);! ! auto threadC = std::thread([&](){! sbfMesh tmp;! //Construct C letter! // ... //! c->addMesh(part4.get());! });! ! auto threadPlus = std::thread([&](){! sbfMesh tmp;! //Construct plus sign! // ... //! plus->translate(2.5, 12.5, 0);! });! ! threadC.join();! threadPlus.join();! ! // Use of "c" and "plus" to make mesh//! ! return mesh;! } 18  
  • 19. MPI   Message  Passing  Interface  (MPI,  интерфейс  передачи   сообщений)  —  программный  интерфейс  для  передачи   информации,  который  позволяет  обмениваться  сообщениями   между  процессами,  выполняющими  одну  задачу.  //Wikipedia   MPI_Comm_size  (comm,&size)   MPI_Comm_rank  (comm,&rank)     MPI_Send(&buffer,count,type,dest,tag,comm)   MPI_Isend(&buffer,count,type,dest,tag,comm,request)   MPI_Recv(&buffer,count,type,source,tag,comm,status)   MPI_Irecv(&buffer,count,type,source,tag,comm,request)     MPI_Bcast  (&buffer,count,datatype,root,comm)   MPI_Reduce  (&sendbuf,&recvbuf,count,datatype,op,root,comm)   MPI_Allreduce  (&sendbuf,&recvbuf,count,datatype,op,comm)     MPI_Barrier  (comm)   19  
  • 20. Ветка:   Коммит:   Использование  MPI   MPI   b42b24a   CMakeLists.txt! ! find_package(MPI REQUIRED)! include_directories(${MPI_INCLUDE_PATH})! target_link_libraries(${PROJECT_NAME} ${MPI_LIBRARIES})! set(CMAKE_CXX_COMPILE_FLAGS ${CMAKE_CXX_COMPILE_FLAGS} ${MPI_COMPILE_FLAGS})! set(CMAKE_CXX_LINK_FLAGS ${CMAKE_CXX_LINK_FLAGS} ${MPI_LINK_FLAGS})! ! main.cpp! ! #include <mpi.h>! // ... //! MPI_Init(&argc, &argv);! int procID, numProcs;! MPI_Comm_size(MPI_COMM_WORLD, &numProcs);! MPI_Comm_rank(MPI_COMM_WORLD, &procID);! ! // Create appropriate mesh! std::unique_ptr<sbfMesh> meshPtr(new sbfMesh);! if ( procID == 0 ) if( recreateMesh || meshPtr->readMeshFromFiles() ){! meshPtr.reset(createMesh(discretParam));! }! sbfMesh *mesh = meshPtr.get();! const int numNodes = mesh->numNodes();! MPI_Bcast(const_cast<int*>(&numNodes), 1, MPI_INT, 0, MPI_COMM_WORLD);! 20  
  • 21. Ветка:   Коммит:   Использование  MPI   MPI    b42b24a   // Create and compute stiffness matrix! std::unique_ptr<sbfStiffMatrixBlock3x3> stiffPtr(new sbfStiffMatrixBlock3x3);! int numBlocks[2], type;! if ( procID == 0 ) {! stiffPtr.reset(createStiffMatrix(mesh, recreateMesh));! numBlocks[0] = stiffPtr->numBlocks();! numBlocks[1] = stiffPtr->numBlocksAlter();! type = static_cast<int>(stiffPtr->type());! }! MPI_Bcast(numBlocks, 2, MPI_INT, 0, MPI_COMM_WORLD);! MPI_Bcast(&type, 1, MPI_INT, 0, MPI_COMM_WORLD);! if ( procID != 0 ) {! stiffPtr.reset(new sbfStiffMatrixBlock3x3(numBlocks[0], numNodes, numBlocks[1]));! stiffPtr->setType(static_cast<MatrixType>(type));! }! sbfStiffMatrixBlock3x3 *stiff = stiffPtr.get();! MPI_Bcast(const_cast<int *>(stiff->indData()), numBlocks[0], MPI_INT, 0, MPI_COMM_WORLD);! MPI_Bcast(const_cast<int *>(stiff->shiftIndData()), numNodes+1, MPI_INT, 0, MPI_COMM_WORLD);! if (numBlocks[1]) {! MPI_Bcast(const_cast<int *>(stiff->indDataAlter()), numBlocks[1], MPI_INT, 0, MPI_COMM_WORLD);! MPI_Bcast(const_cast<int *>(stiff->shiftIndDataAlter()), numNodes+1, MPI_INT, 0, MPI_COMM_WORLD);! }! MPI_Bcast(const_cast<double *>(stiff->data()), numBlocks[0]*9, MPI_DOUBLE, 0, MPI_COMM_WORLD);! if ( procID != 0 ) stiff->updataAlterPtr();! ! // ... //! ! // Fill mass and demping arrays! if ( procID == 0 ) computeMassDemp(mass, demp, mesh, stiff->propSet(), ksi, recreateMesh);! MPI_Bcast(mass.data(), numNodes*3, MPI_DOUBLE, 0, MPI_COMM_WORLD);! MPI_Bcast(demp.data(), numNodes*3, MPI_DOUBLE, 0, MPI_COMM_WORLD);! 21  
  • 22. Ветка:   Коммит:   Использование  MPI   MPI    b42b24a   // Time integration loop! int nodeStart = numNodes/numProcs*procID;! int nodeStop = procID != numProcs - 1 ? numNodes/numProcs*(procID+1) : numNodes;! if ( procID == 0 ) report.createNewProgress("Time integration");! while( t < tStop ) { // Time loop! // Update displacements of kinematically loaded nodes! // ... //! ! MPI_Bcast(displ.data(), numNodes*3, MPI_DOUBLE, 0, MPI_COMM_WORLD);! rezKU.null();! reduceBuf.null();! for(int nodeCt = nodeStart; nodeCt < nodeStop; nodeCt++) {! // Make multiplication of stiffness matrix over displacement vector! iterator->setToRow(nodeCt);! while(iterator->isValid()) { /* ... */ iterator->next(); }! // Perform finite difference step! for(int ct = 0; ct < 3; ct++) {! // ... //! reduceBuf.data()[3*nodeCt+ct] = temp/(a0*mass.data()[3*nodeCt+ct] + a1*demp.data()[3*nodeCt+ct]);! }! }! MPI_Allreduce(reduceBuf.data(), displ_p1.data(), numNodes*3, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);! ! // Make output if required! if ( procID == 0 ) if(t >= tNextOut) { /* ... */ }! // Prepere for next step! t += dt;! displ_m1.copyData(displ); displ.copyData(displ_p1);! } // End time loop! if ( procID == 0 ) report.finalizeProgress();! ! MPI_Finalize();! 22  
  • 23. Ветка:   Коммит:   MPI  +  потоки   MPI_threads    7b033e3   int nodeStart = numNodes/numProcs*procID;! int nodeStop = procID != numProcs - 1 ? numNodes/numProcs*(procID+1) : numNodes;! ! for(int ct = 0; ct < numThreads; ct++) {! eventsStart.push_back(new event);! eventsStop.push_back(new event);! int threadStartNode = nodeStart + (nodeStop - nodeStart)/numThreads*ct;! int threadStopNode = nodeStart + (nodeStop - nodeStart)/numThreads*(ct+1);! if(ct == numThreads-1) threadStopNode = nodeStop;! threads[ct] = std::thread(std::bind(procFunc, threadStartNode, threadStopNode, eventsStart[ct], eventsStop[ct]));! threads[ct].detach();! }! for(auto ev : eventsStop) ev->wait();! ! // Time integration loop! if ( procID == 0 ) report.createNewProgress("Time integration");! while( t < tStop ) { // Time loop! // Update displacements of kinematically loaded nodes! ! MPI_Bcast(displ.data(), numNodes*3, MPI_DOUBLE, 0, MPI_COMM_WORLD);! rezKU.null(); reduceBuf.null();! for(auto ev : eventsStart) ev->set();! for(auto ev : eventsStop) ev->wait();! MPI_Allreduce(reduceBuf.data(), displ_p1.data(), numNodes*3, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);! ! // Make output if required! if ( procID == 0 ) if(t >= tNextOut) { /* ... */}! // Prepere for next step! t += dt; displ_m1.copyData(displ); displ.copyData(displ_p1);! } // End time loop! if ( procID == 0 ) report.finalizeProgress(); 23  
  • 24. Вместо  выводов   Один  поток   openMP   threads   MPI   MPI  +   threads   97   20   21   42   31   IMHO:   •  При  современном  развитии  вычислительной  техники  разработчику  непростительно   написание  не  параллельных  программ,  особенно  в  области  расчетов   •  Современные  стандарты  и  их  реализации  позволяют  относительно  быстро   внедрять  их  в  существующие  или  вновь  создаваемые  проекты   •  Хотя,  возможно  в  ближайшем  будущем  компиляторы  научатся  делать  все  за  нас  :)   24  
  • 25. Крутько  Евгений   e.s.krutko@gmail.com   google.com/+ЕвгенийКрутько   Репозиторий  проекта:   hnps://github.com/eskrut/directIntegra-onSolver.git   25