simulation is on different thread

main
Benjamin Kraft 1 year ago
parent a3d04d3086
commit c9a281fbb3
  1. 3
      CMakeLists.txt
  2. 3
      src/GLWidget.cpp
  3. 18
      src/MainWindow.cpp
  4. 4
      src/MainWindow.h
  5. 15
      src/Simulation.cpp
  6. 14
      src/Simulation.h
  7. 29
      src/main.cpp

@ -8,10 +8,11 @@ set(CMAKE_AUTOUIC ON)
find_package(Qt6 COMPONENTS OpenGLWidgets REQUIRED)
find_package(Eigen3 REQUIRED)
find_package(OpenMP REQUIRED)
file(GLOB_RECURSE SOURCE_FILES src/**.cpp)
add_executable(Pendulum WIN32 ${SOURCE_FILES} icons/icons.qrc)
include_directories(${EIGEN3_INCLUDE_DIR})
target_link_libraries(Pendulum Qt6::OpenGLWidgets)
target_link_libraries(Pendulum Qt6::OpenGLWidgets OpenMP::OpenMP_CXX)

@ -33,8 +33,9 @@ void GLWidget::timerEvent(QTimerEvent *e) {
void GLWidget::updateFPS() {
auto thisFrame = high_resolution_clock::now();
auto diff = duration_cast<milliseconds>(thisFrame - previousFrame).count();
auto diff = (int)duration_cast<milliseconds>(thisFrame - previousFrame).count();
currentFPS = 1000 / (diff == 0 ? 1 : diff);
// std::cout << currentFPS << std::endl;
previousFrame = thisFrame;
}

@ -14,9 +14,15 @@
#include <QCoreApplication>
#include "Pendulum.h"
#include "Button.h"
#include <QThread>
#include <QCloseEvent>
#include <QTimer>
MainWindow::MainWindow() {
simulationThread = new QThread(this);
simulation = new Simulation;
simulation->moveToThread(simulationThread);
simulationThread->start();
masses = std::vector<double>(MaxSegments);
lengths = std::vector<double>(MaxSegments);
@ -291,7 +297,7 @@ QWidget * MainWindow::buildAddUI() {
removeBtn->setStyleSheet("background-color: #ffaaaa");
connect(addBtn, &QPushButton::clicked, this, &MainWindow::add);
connect(removeBtn, &QPushButton::clicked, this, &MainWindow::remove);
connect(removeBtn, &QPushButton::clicked, simulation, &Simulation::clearPendula);
btnLyt->addWidget(addBtn);
btnLyt->addWidget(removeBtn);
@ -420,10 +426,6 @@ void MainWindow::add() {
}
}
void MainWindow::remove() {
simulation->clearPendula();
}
void MainWindow::resetSimulationControl() {
gravitySlider->setValue(981);
timescaleSlider->setValue(100);
@ -433,3 +435,9 @@ void MainWindow::resetSimulationControl() {
void MainWindow::toggleSimulation() {
simulation->isPlaying = !simulation->isPlaying;
}
void MainWindow::closeEvent(QCloseEvent *e) {
simulationThread->quit();
simulationThread->wait();
e->accept();
}

@ -11,11 +11,14 @@ enum Property {Angle, Mass, Length};
class MainWindow : public QWidget {
public:
explicit MainWindow();
protected:
void closeEvent(QCloseEvent*) override;
private:
void buildUI();
QWidget * buildAddUI();
QWidget * buildSimulationUI();
Simulation * simulation;
QThread * simulationThread;
GLWidget * glWidget = nullptr;
@ -42,7 +45,6 @@ public slots:
void resetLengths();
void normalizeLengths();
void add();
void remove();
void resetSimulationControl();
void toggleSimulation();

@ -2,12 +2,16 @@
#include "Pendulum.h"
#include <QPainter>
#include <QTimer>
#include <QThread>
#include <omp.h>
#include <iostream>
Simulation::Simulation() {
timer = new QTimer(this);
QTimer::connect(timer, &QTimer::timeout, this, &Simulation::update);
timer->setInterval(updateInterval);
timer->start();
lastUpdate = high_resolution_clock::now();
};
void Simulation::draw(QPainter *p, int screenSize) const {
@ -18,6 +22,11 @@ void Simulation::draw(QPainter *p, int screenSize) const {
}
void Simulation::update() {
auto thisUpdate = high_resolution_clock::now();
auto ms = (int)duration_cast<milliseconds>(thisUpdate - lastUpdate).count();
// std::cout << ms << std::endl;
lastUpdate = thisUpdate;
if (!isPlaying)
return;
@ -25,8 +34,9 @@ void Simulation::update() {
h /= substeps;
for (int i = 0; i < substeps; i++)
for (const auto pendulum : pendula)
#pragma omp parallel for
for (const auto pendulum : pendula)
for (int i = 0; i < substeps; i++)
pendulum->update(h, gravity);
}
@ -35,3 +45,4 @@ void Simulation::clearPendula() {
delete p;
pendula.clear();
}

@ -1,6 +1,9 @@
#include <vector>
#include <cstdint>
#include <QObject>
#include <chrono>
using namespace std::chrono;
class Pendulum;
class QPainter;
@ -12,20 +15,23 @@ public:
double size = 50;
double gravity;
double timescale;
int substeps;
double gravity {};
double timescale {};
int substeps {};
int updateInterval = 17;
bool isPlaying = false;
std::vector<Pendulum *> pendula;
void clearPendula();
QTimer * timer;
void draw(QPainter*, int) const;
public slots:
void clearPendula();
private slots:
void update();
private:
time_point<system_clock> lastUpdate;
};

@ -1,6 +1,11 @@
#include <QApplication>
#include <QSurfaceFormat>
#include "MainWindow.h"
#include <omp.h>
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
@ -12,5 +17,29 @@ int main(int argc, char* argv[]) {
MainWindow w;
w.show();
for (int threads = 1; threads <= 16; threads++){
int num_steps = 100'000;
double step = 1.0 / double(num_steps);
omp_set_num_threads(threads);
double pi = 0;
auto t = high_resolution_clock ::now();
#pragma omp parallel
{
int numThreads = omp_get_num_threads();
int threadId = omp_get_thread_num();
int i;
double localSum = 0;
for (i = threadId; i < num_steps; i += numThreads){
double x = (i + 0.5) * step;
localSum += 4.0 / (1.0 + x * x);
}
#pragma omp atomic
pi += localSum * step;
}
std::cout << threads << " " << duration_cast<microseconds>(high_resolution_clock::now() - t).count() << " ";
std::cout << pi << std::endl;
}
return QApplication::exec();
}

Loading…
Cancel
Save