diff --git a/Framework/MDAlgorithms/inc/MantidMDAlgorithms/BinMD.h b/Framework/MDAlgorithms/inc/MantidMDAlgorithms/BinMD.h
index f647d3ab675ded2c0b98c21243844f151781c6c8..a6561eb5c7bf77e94bb97e4476e0ebaf56a4dd75 100644
--- a/Framework/MDAlgorithms/inc/MantidMDAlgorithms/BinMD.h
+++ b/Framework/MDAlgorithms/inc/MantidMDAlgorithms/BinMD.h
@@ -80,6 +80,7 @@ private:
   signal_t *signals;
   signal_t *errors;
   signal_t *numEvents;
+  bool m_accumulate{false};
 };
 
 } // namespace Mantid
diff --git a/Framework/MDAlgorithms/inc/MantidMDAlgorithms/MDNormDirectSC.h b/Framework/MDAlgorithms/inc/MantidMDAlgorithms/MDNormDirectSC.h
index 0de81b108752920c5b332ca704bf506f4c33e8a8..9e05a140fe0fb07843902ccd82a731cacddc7f9d 100644
--- a/Framework/MDAlgorithms/inc/MantidMDAlgorithms/MDNormDirectSC.h
+++ b/Framework/MDAlgorithms/inc/MantidMDAlgorithms/MDNormDirectSC.h
@@ -85,6 +85,7 @@ private:
   Kernel::V3D m_beamDir;
   /// ki-kf for Inelastic convention; kf-ki for Crystallography convention
   std::string convention;
+  bool m_accumulate{false};
 };
 
 } // namespace MDAlgorithms
diff --git a/Framework/MDAlgorithms/inc/MantidMDAlgorithms/MDNormSCD.h b/Framework/MDAlgorithms/inc/MantidMDAlgorithms/MDNormSCD.h
index 0a88fa8bf704d547da4179bf83779386a5e63087..5b18915c2920df28b5675b3151318e5ead64e9d8 100644
--- a/Framework/MDAlgorithms/inc/MantidMDAlgorithms/MDNormSCD.h
+++ b/Framework/MDAlgorithms/inc/MantidMDAlgorithms/MDNormSCD.h
@@ -88,6 +88,7 @@ private:
   Kernel::V3D m_beamDir;
   /// ki-kf for Inelastic convention; kf-ki for Crystallography convention
   std::string convention;
+  bool m_accumulate{false};
 };
 
 } // namespace MDAlgorithms
diff --git a/Framework/MDAlgorithms/src/BinMD.cpp b/Framework/MDAlgorithms/src/BinMD.cpp
index 8ef1de8bd55e109ed19c6a8e3b4b871f2cfe5e2d..6b9329de523da2cfa1201f8fc4c74b7040dcefb6 100644
--- a/Framework/MDAlgorithms/src/BinMD.cpp
+++ b/Framework/MDAlgorithms/src/BinMD.cpp
@@ -75,8 +75,9 @@ void BinMD::init() {
       "due to disk thrashing.");
   setPropertyGroup("Parallel", grp);
 
-  declareProperty(make_unique<WorkspaceProperty<IMDWorkspace>>(
-                      "TemporaryDataWorkspace", "", Direction::Input),
+  declareProperty(make_unique<WorkspaceProperty<IMDHistoWorkspace>>(
+                      "TemporaryDataWorkspace", "", Direction::Input,
+                      PropertyMode::Optional),
                   "An input MDWorkspace.");
 
   declareProperty(make_unique<WorkspaceProperty<Workspace>>(
@@ -249,8 +250,10 @@ void BinMD::binByIterating(typename MDEventWorkspace<MDE, nd>::sptr ws) {
   errors = outWS->getErrorSquaredArray();
   numEvents = outWS->getNumEventsArray();
 
-  // Start with signal/error/numEvents at 0.0
-  outWS->setTo(0.0, 0.0, 0.0);
+  if (!m_accumulate) {
+    // Start with signal/error/numEvents at 0.0
+    outWS->setTo(0.0, 0.0, 0.0);
+  }
 
   // The dimension (in the output workspace) along which we chunk for parallel
   // processing
@@ -274,10 +277,10 @@ void BinMD::binByIterating(typename MDEventWorkspace<MDE, nd>::sptr ws) {
 
   // Total number of steps
   size_t progNumSteps = 0;
-  if (prog)
+  if (prog) {
     prog->setNotifyStep(0.1);
-  if (prog)
     prog->resetNumSteps(100, 0.00, 1.0);
+  }
 
   // Run the chunks in parallel. There is no overlap in the output workspace so
   // it is thread safe to write to it..
@@ -380,11 +383,13 @@ void BinMD::exec() {
   prog = new Progress(this, 0, 1.0, 1);
 
   // Create the dense histogram. This allocates the memory
-  outWS = this->getProperty("TemporaryDataWorkspace");
-  if (outWS) {
-    outWS->setTo(0., 0., 0.);
-  } else {
+  boost::shared_ptr<IMDHistoWorkspace> tmp =
+      this->getProperty("TemporaryDataWorkspace");
+  outWS = boost::dynamic_pointer_cast<MDHistoWorkspace>(tmp);
+  if (!outWS) {
     outWS = boost::make_shared<MDHistoWorkspace>(m_binDimensions);
+  } else {
+    m_accumulate = true;
   }
 
   // Saves the geometry transformation from original to binned in the workspace
diff --git a/Framework/MDAlgorithms/src/MDNormDirectSC.cpp b/Framework/MDAlgorithms/src/MDNormDirectSC.cpp
index c318f0e698449b14a688918d9310a76da84e2771..8f5e8525555c27a8523fc46c40a1b3647eeb6ab9 100644
--- a/Framework/MDAlgorithms/src/MDNormDirectSC.cpp
+++ b/Framework/MDAlgorithms/src/MDNormDirectSC.cpp
@@ -106,12 +106,14 @@ void MDNormDirectSC::init() {
                   "ConvertToMD algorithm was run, and assume that the direct "
                   "geometry inelastic mode is used.");
 
-  declareProperty(make_unique<WorkspaceProperty<MDHistoWorkspace>>(
-                      "TemporaryNormalizationWorkspace", "", Direction::Input),
+  declareProperty(make_unique<WorkspaceProperty<IMDHistoWorkspace>>(
+                      "TemporaryNormalizationWorkspace", "", Direction::Input,
+                      PropertyMode::Optional),
                   "Input normalization MDHistoWorkspace.");
 
-  declareProperty(make_unique<WorkspaceProperty<IMDWorkspace>>(
-                      "TemporaryDataWorkspace", "", Direction::Input),
+  declareProperty(make_unique<WorkspaceProperty<IMDHistoWorkspace>>(
+                      "TemporaryDataWorkspace", "", Direction::Input,
+                      PropertyMode::Optional),
                   "An input MDWorkspace.");
 
   declareProperty(make_unique<WorkspaceProperty<Workspace>>(
@@ -274,11 +276,15 @@ MDHistoWorkspace_sptr MDNormDirectSC::binInputWS() {
  */
 void MDNormDirectSC::createNormalizationWS(const MDHistoWorkspace &dataWS) {
   // Copy the MDHisto workspace, and change signals and errors to 0.
-  m_normWS = this->getProperty("TemporaryNormalizationWorkspace");
+  boost::shared_ptr<IMDHistoWorkspace> tmp =
+      this->getProperty("TemporaryNormalizationWorkspace");
+  m_normWS = boost::dynamic_pointer_cast<MDHistoWorkspace>(tmp);
   if (!m_normWS) {
     m_normWS = dataWS.clone();
+    m_normWS->setTo(0., 0., 0.);
+  } else {
+    m_accumulate = true;
   }
-  m_normWS->setTo(0., 0., 0.);
 }
 
 /**
@@ -537,7 +543,15 @@ for (int64_t i = 0; i < ndets; i++) {
   PARALLEL_END_INTERUPT_REGION
 }
 PARALLEL_CHECK_INTERUPT_REGION
-std::copy(signalArray.cbegin(), signalArray.cend(), m_normWS->getSignalArray());
+if (m_accumulate) {
+  std::transform(
+      signalArray.cbegin(), signalArray.cend(), m_normWS->getSignalArray(),
+      m_normWS->getSignalArray(),
+      [](const std::atomic<signal_t> &a, const signal_t &b) { return a + b; });
+} else {
+  std::copy(signalArray.cbegin(), signalArray.cend(),
+            m_normWS->getSignalArray());
+}
 }
 
 /**
diff --git a/Framework/MDAlgorithms/src/MDNormSCD.cpp b/Framework/MDAlgorithms/src/MDNormSCD.cpp
index 1b0fa83ee0caa6e2e37f55e275a18b0d9cb45e29..d80d83dabff0a28c37b9003aba6f4b863a34d726 100644
--- a/Framework/MDAlgorithms/src/MDNormSCD.cpp
+++ b/Framework/MDAlgorithms/src/MDNormSCD.cpp
@@ -102,12 +102,14 @@ void MDNormSCD::init() {
                   "An input workspace containing momentum integrated vanadium "
                   "(a measure of the solid angle).");
 
-  declareProperty(make_unique<WorkspaceProperty<MDHistoWorkspace>>(
-                      "TemporaryNormalizationWorkspace", "", Direction::Input),
+  declareProperty(make_unique<WorkspaceProperty<IMDHistoWorkspace>>(
+                      "TemporaryNormalizationWorkspace", "", Direction::Input,
+                      PropertyMode::Optional),
                   "Input normalization MDHistoWorkspace.");
 
-  declareProperty(make_unique<WorkspaceProperty<IMDWorkspace>>(
-                      "TemporaryDataWorkspace", "", Direction::Input),
+  declareProperty(make_unique<WorkspaceProperty<IMDHistoWorkspace>>(
+                      "TemporaryDataWorkspace", "", Direction::Input,
+                      PropertyMode::Optional),
                   "An input MDWorkspace.");
 
   declareProperty(make_unique<WorkspaceProperty<Workspace>>(
@@ -239,12 +241,15 @@ MDHistoWorkspace_sptr MDNormSCD::binInputWS() {
  */
 void MDNormSCD::createNormalizationWS(const MDHistoWorkspace &dataWS) {
   // Copy the MDHisto workspace, and change signals and errors to 0.
-
-  m_normWS = this->getProperty("TemporaryNormalizationWorkspace");
+  boost::shared_ptr<IMDHistoWorkspace> tmp =
+      this->getProperty("TemporaryNormalizationWorkspace");
+  m_normWS = boost::dynamic_pointer_cast<MDHistoWorkspace>(tmp);
   if (!m_normWS) {
     m_normWS = dataWS.clone();
+    m_normWS->setTo(0., 0., 0.);
+  } else {
+    m_accumulate = true;
   }
-  m_normWS->setTo(0., 0., 0.);
 }
 
 /**
@@ -490,7 +495,15 @@ for (int64_t i = 0; i < ndets; i++) {
   PARALLEL_END_INTERUPT_REGION
 }
 PARALLEL_CHECK_INTERUPT_REGION
-std::copy(signalArray.cbegin(), signalArray.cend(), m_normWS->getSignalArray());
+if (m_accumulate) {
+  std::transform(
+      signalArray.cbegin(), signalArray.cend(), m_normWS->getSignalArray(),
+      m_normWS->getSignalArray(),
+      [](const std::atomic<signal_t> &a, const signal_t &b) { return a + b; });
+} else {
+  std::copy(signalArray.cbegin(), signalArray.cend(),
+            m_normWS->getSignalArray());
+}
 }
 
 /**