diff --git a/agui2/src/Execution/ParallelExecutor.cpp b/agui2/src/Execution/ParallelExecutor.cpp
index b8dd613d388a9360f0c458467396a0c1bf73287b..f582690b9a0c3dae5c7ff32388f73d33772ce7fd 100644
--- a/agui2/src/Execution/ParallelExecutor.cpp
+++ b/agui2/src/Execution/ParallelExecutor.cpp
@@ -10,13 +10,12 @@
 #include <Models/OutputModelBox.hpp>
 #include <exception/CommonException.h>
 
-Q_GLOBAL_STATIC(ParallelExecutor, parallelExecutorInstance);
-
 std::shared_ptr<abstraction::OperationAbstraction> ParallelExecutor::execute(OutputModelBox* output) {
 
-    for (auto* box: this->modelBoxes) {
+    for (auto* box: ModelBox::getAllModelBoxes()) {
         box->id = static_cast<size_t>(-1);
         box->level = static_cast<size_t>(-1);
+        box->clearCachedResult();
     }
 
     // collect all boxes leading to the output box
@@ -165,22 +164,9 @@ std::shared_ptr<abstraction::OperationAbstraction> ParallelExecutor::execute(Out
 
         std::vector<std::future<void>> futures;
         for (auto* box: level) {
-            futures.push_back(std::async(std::launch::async, [=]{ box->run(); }));
+            futures.push_back(std::async(std::launch::async, [=]{ box->getCachedResultOrEvaluate(); }));
         }
     }
 
-    return output->getResult();
-}
-
-ParallelExecutor* ParallelExecutor::getInstance() {
-    return parallelExecutorInstance;
-}
-
-void ParallelExecutor::addModelBox(ModelBox* modelBox) {
-    this->modelBoxes.push_back(modelBox);
-}
-
-void ParallelExecutor::removeModelBox(ModelBox* modelBox) {
-    auto& bs = this->modelBoxes;
-    bs.erase(std::remove(bs.begin(), bs.end(), modelBox), bs.end());
-}
+    return output->getCachedResult();
+}
\ No newline at end of file
diff --git a/agui2/src/Execution/ParallelExecutor.hpp b/agui2/src/Execution/ParallelExecutor.hpp
index fe4418606fffa32962bd36c31593939d4329975b..d3cc2e43156b4a49ed4b9e430c4911434b7f57e4 100644
--- a/agui2/src/Execution/ParallelExecutor.hpp
+++ b/agui2/src/Execution/ParallelExecutor.hpp
@@ -7,16 +7,7 @@
 
 class ParallelExecutor {
 public:
-
-    std::shared_ptr<abstraction::OperationAbstraction> execute(OutputModelBox* output);
-
-    void addModelBox(ModelBox* modelBox);
-    void removeModelBox(ModelBox* modelBox);
-
-    static ParallelExecutor* getInstance();
-
-private:
-    std::vector<ModelBox*> modelBoxes;
+    static std::shared_ptr<abstraction::OperationAbstraction> execute(OutputModelBox* output);
 };
 
 
diff --git a/agui2/src/MainWindow.cpp b/agui2/src/MainWindow.cpp
index 53c956c88a4bd6bea63043a1a48e9e84859c728d..3897d6c69c1490af913a444750771258c56f6772 100644
--- a/agui2/src/MainWindow.cpp
+++ b/agui2/src/MainWindow.cpp
@@ -58,10 +58,10 @@ void MainWindow::on_RunBtn_clicked()
     std::shared_ptr<abstraction::OperationAbstraction> result;
     try {
 #if 0
-        this->outputBox->getModelBox()->clearResultRecursive();
+        ModelBox::clearCachedResults();
         result = this->outputBox->getModelBox()->run();
 #else
-        result = ParallelExecutor::getInstance()->execute(dynamic_cast<OutputModelBox*>(this->outputBox->getModelBox()));
+        result = ParallelExecutor::execute(dynamic_cast<OutputModelBox*>(this->outputBox->getModelBox()));
 #endif
     }
     catch (const exception::CommonException& e) {
diff --git a/agui2/src/Models/AlgorithmModelBox.cpp b/agui2/src/Models/AlgorithmModelBox.cpp
index 261ad6a481a1467a66867002ea13237f8b1e5a90..ac16d04ddb4d3966f892260df24f1da32f7a6d66 100644
--- a/agui2/src/Models/AlgorithmModelBox.cpp
+++ b/agui2/src/Models/AlgorithmModelBox.cpp
@@ -10,17 +10,18 @@ AlgorithmModelBox::AlgorithmModelBox(Algorithm* algorithm)
     : ModelBox(ModelType::Algorithm, algorithm->getInputCount())
     , algorithm(algorithm) {}
 
-std::shared_ptr<abstraction::OperationAbstraction> AlgorithmModelBox::runInternal() {
+std::shared_ptr<abstraction::OperationAbstraction> AlgorithmModelBox::evaluate() {
     std::vector<std::shared_ptr<abstraction::OperationAbstraction>> params;
     for (auto* input: this->inputs)
     {
         if (!input)
             return nullptr;
-        params.push_back(input->run());
+        params.push_back(input->getCachedResultOrEvaluate());
         if (!params.back())
             return nullptr;
     }
-    return this->algorithm->execute(params);
+    this->result = this->algorithm->execute(params);
+    return this->result;
 }
 
 std::string AlgorithmModelBox::getName() const {
diff --git a/agui2/src/Models/AlgorithmModelBox.hpp b/agui2/src/Models/AlgorithmModelBox.hpp
index 6aa0293628917c25af5eb40f35a07fc6af0c330d..d42b462a34f8d8cb1c372424693bdfa9db5788c8 100644
--- a/agui2/src/Models/AlgorithmModelBox.hpp
+++ b/agui2/src/Models/AlgorithmModelBox.hpp
@@ -9,8 +9,7 @@ public:
     std::string getName() const override;
     Algorithm* getAlgorithm() const { return this->algorithm; }
 
-protected:
-    std::shared_ptr<abstraction::OperationAbstraction> runInternal() override;
+    std::shared_ptr<abstraction::OperationAbstraction> evaluate() override;
 
 private:
     Algorithm* algorithm;
diff --git a/agui2/src/Models/InputModelBox.cpp b/agui2/src/Models/InputModelBox.cpp
index 0456e740c80680b0dd60e5a823b68b39274049ed..c1fd66ba8a468162015a9ea0e4de6626632db201 100644
--- a/agui2/src/Models/InputModelBox.cpp
+++ b/agui2/src/Models/InputModelBox.cpp
@@ -4,7 +4,7 @@ InputModelBox::InputModelBox()
     : ModelBox(ModelType::Input, 0)
 {}
 
-std::shared_ptr<abstraction::OperationAbstraction> InputModelBox::runInternal() {
+std::shared_ptr<abstraction::OperationAbstraction> InputModelBox::evaluate() {
     return this->result;
 }
 
diff --git a/agui2/src/Models/InputModelBox.hpp b/agui2/src/Models/InputModelBox.hpp
index 8e4a01105fde3260d5c01b0dc0db50a30632b53b..9347b7ba1e5fdd6bd6e418f9c7e5a0a5b2eb0392 100644
--- a/agui2/src/Models/InputModelBox.hpp
+++ b/agui2/src/Models/InputModelBox.hpp
@@ -6,9 +6,9 @@ class InputModelBox : public ModelBox {
 public:
     explicit InputModelBox();
 
-    void clearResultRecursive() override {}
+    void clearCachedResult() override {}
 
-    std::shared_ptr<abstraction::OperationAbstraction> runInternal() override;
+    std::shared_ptr<abstraction::OperationAbstraction> evaluate() override;
 
     std::string getName() const override;
 
diff --git a/agui2/src/Models/ModelBox.cpp b/agui2/src/Models/ModelBox.cpp
index 89ef621d549504b9d2c454a23e6c3f3e9f43a735..5658dff5649cc3f70d135bce39de4e7084b5547d 100644
--- a/agui2/src/Models/ModelBox.cpp
+++ b/agui2/src/Models/ModelBox.cpp
@@ -6,6 +6,8 @@
 
 #include <Execution/ParallelExecutor.hpp>
 
+std::vector<ModelBox*> ModelBox::allModelBoxes;
+
 ModelBox::ModelBox(ModelType type, uint8_t maxInputCount)
     : type(type)
     , maxInputCount(maxInputCount)
@@ -13,11 +15,12 @@ ModelBox::ModelBox(ModelType type, uint8_t maxInputCount)
 {
     // Input box cannot have inputs, other boxes must have inputs
     Q_ASSERT((this->type == ModelType::Input) == (this->maxInputCount == 0));
-    ParallelExecutor::getInstance()->addModelBox(this);
+    ModelBox::allModelBoxes.push_back(this);
 }
 
 ModelBox::~ModelBox() {
-    ParallelExecutor::getInstance()->removeModelBox(this);
+    auto& bs = ModelBox::allModelBoxes;
+    bs.erase(std::remove(bs.begin(), bs.end(), this), bs.end());
 }
 
 void ModelBox::setInput(uint8_t slot, ModelBox* model) {
@@ -35,17 +38,14 @@ void ModelBox::removeOutput(ModelBox* model, uint8_t slot) {
     this->outputs.erase({model, slot});
 }
 
-std::shared_ptr<abstraction::OperationAbstraction> ModelBox::run() {
-    if (!this->result)
-        this->result = this->runInternal();
-
-    return this->result;
+std::shared_ptr<abstraction::OperationAbstraction> ModelBox::getCachedResultOrEvaluate() {
+    if (this->result)
+        return this->result;
+    return this->evaluate();
 }
 
-void ModelBox::clearResultRecursive() {
-    this->result.reset();
-    for (auto* input: this->inputs) {
-        input->clearResultRecursive();
+void ModelBox::clearCachedResults() {
+    for (auto* box: ModelBox::allModelBoxes) {
+        box->clearCachedResult();
     }
-
 }
diff --git a/agui2/src/Models/ModelBox.hpp b/agui2/src/Models/ModelBox.hpp
index 747c27d97072096df4117ee50b543ba5584c014e..8af9450d2b8e6a40097e91cbdfa7e258815d9eb3 100644
--- a/agui2/src/Models/ModelBox.hpp
+++ b/agui2/src/Models/ModelBox.hpp
@@ -33,14 +33,15 @@ public:
     uint8_t getMaxInputCount() const { return this->maxInputCount; }
     virtual bool canHaveOutput() const { return true; }
 
-    std::shared_ptr<abstraction::OperationAbstraction> getResult() const { return this->result; }
-    virtual void clearResultRecursive();
+    std::shared_ptr<abstraction::OperationAbstraction> getCachedResult() const { return this->result; }
+    std::shared_ptr<abstraction::OperationAbstraction> getCachedResultOrEvaluate();
+    virtual void clearCachedResult() { this->result.reset(); }
+    virtual std::shared_ptr<abstraction::OperationAbstraction> evaluate() = 0;
 
-    std::shared_ptr<abstraction::OperationAbstraction> run();
+    static const std::vector<ModelBox*>& getAllModelBoxes() { return ModelBox::allModelBoxes; }
+    static void clearCachedResults();
 
 protected:
-    virtual std::shared_ptr<abstraction::OperationAbstraction> runInternal() = 0;
-
     ModelType type;
 
     uint8_t maxInputCount = 0;
@@ -51,6 +52,8 @@ protected:
     GraphicsBox* graphicsBox = nullptr;
 
 private:
+    static std::vector<ModelBox*> allModelBoxes;
+
     // for topological sorting in ParallelExecutor
     mutable size_t id = static_cast<size_t>(-1);
     mutable size_t level = static_cast<size_t>(-1);
diff --git a/agui2/src/Models/OutputModelBox.cpp b/agui2/src/Models/OutputModelBox.cpp
index b7a54af9f471ae0a608f7d264d6c86f800444813..13c2e21fc9f4e2404f5c8207b749e4c8720dad36 100644
--- a/agui2/src/Models/OutputModelBox.cpp
+++ b/agui2/src/Models/OutputModelBox.cpp
@@ -6,11 +6,11 @@ OutputModelBox::OutputModelBox()
     : ModelBox(ModelType::Output, 1)
 {}
 
-std::shared_ptr<abstraction::OperationAbstraction> OutputModelBox::runInternal() {
+std::shared_ptr<abstraction::OperationAbstraction> OutputModelBox::evaluate() {
     assert(this->inputs.size() == 1);
     if (!this->inputs[0])
         return nullptr;
-    return inputs[0]->run();
+    return inputs[0]->getCachedResultOrEvaluate();
 }
 
 std::string OutputModelBox::getName() const {
diff --git a/agui2/src/Models/OutputModelBox.hpp b/agui2/src/Models/OutputModelBox.hpp
index 3bfb8545b20d6c33077e163cdfcd835a6d8a77e1..03e630a2c23c8b398e3bf67fa3bf77f100e93746 100644
--- a/agui2/src/Models/OutputModelBox.hpp
+++ b/agui2/src/Models/OutputModelBox.hpp
@@ -9,7 +9,7 @@ public:
 
     bool canHaveOutput() const override { return false; }
 
-    std::shared_ptr<abstraction::OperationAbstraction> runInternal() override;
+    std::shared_ptr<abstraction::OperationAbstraction> evaluate() override;
 };