Index: stable/HeuristicLab.Optimization.Operators/3.3/SolutionSimilarityCalculator.cs
===================================================================
--- stable/HeuristicLab.Optimization.Operators/3.3/SolutionSimilarityCalculator.cs	(revision 13134)
+++ stable/HeuristicLab.Optimization.Operators/3.3/SolutionSimilarityCalculator.cs	(revision 13170)
@@ -22,4 +22,5 @@
 using System;
 using System.Linq;
+using System.Threading.Tasks;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -41,4 +42,8 @@
     [Storable]
     public string QualityVariableName { get; set; }
+    [Storable]
+    public bool ExecuteInParallel { get; set; }
+    [Storable]
+    public int MaxDegreeOfParallelism { get; set; }
     #endregion
 
@@ -48,8 +53,22 @@
     protected SolutionSimilarityCalculator(SolutionSimilarityCalculator original, Cloner cloner)
       : base(original, cloner) {
-      this.SolutionVariableName = original.SolutionVariableName;
-      this.QualityVariableName = original.QualityVariableName;
-    }
-    protected SolutionSimilarityCalculator() : base() { }
+      SolutionVariableName = original.SolutionVariableName;
+      QualityVariableName = original.QualityVariableName;
+      ExecuteInParallel = original.ExecuteInParallel;
+      MaxDegreeOfParallelism = original.MaxDegreeOfParallelism;
+    }
+
+    protected SolutionSimilarityCalculator() : base() {
+      ExecuteInParallel = false;
+      MaxDegreeOfParallelism = -1;
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (MaxDegreeOfParallelism == 0) {
+        ExecuteInParallel = false;
+        MaxDegreeOfParallelism = -1;
+      }
+    }
 
     public double[][] CalculateSolutionCrowdSimilarity(IScope leftSolutionCrowd, IScope rightSolutionCrowd) {
@@ -75,27 +94,51 @@
 
     public double[][] CalculateSolutionCrowdSimilarity(IScope solutionCrowd) {
-      if (solutionCrowd == null)
+      if (solutionCrowd == null) {
         throw new ArgumentException("Cannot calculate similarity because the provided crowd is null.");
-
+      }
       var individuals = solutionCrowd.SubScopes;
 
-      if (!individuals.Any())
+      if (!individuals.Any()) {
         throw new ArgumentException("Cannot calculate similarity because the provided crowd is empty.");
+      }
 
       var similarityMatrix = new double[individuals.Count][];
-      for (int i = 0; i < individuals.Count; i++) similarityMatrix[i] = new double[individuals.Count];
-
-      if (IsCommutative) {
-        for (int i = 0; i < individuals.Count; i++) {
-          for (int j = i; j < individuals.Count; j++) {
-            similarityMatrix[i][j] = similarityMatrix[j][i] = CalculateSolutionSimilarity(individuals[i], individuals[j]);
+      for (int i = 0; i < individuals.Count; i++) {
+        similarityMatrix[i] = new double[individuals.Count];
+      }
+
+      if (ExecuteInParallel) {
+        var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = MaxDegreeOfParallelism };
+        if (IsCommutative) {
+          Parallel.For(0, individuals.Count, parallelOptions, i => {
+            for (int j = i; j < individuals.Count; j++) {
+              similarityMatrix[i][j] =
+                similarityMatrix[j][i] = CalculateSolutionSimilarity(individuals[i], individuals[j]);
+            }
+          });
+        } else {
+          Parallel.For(0, individuals.Count, parallelOptions, i => {
+            for (int j = i; j < individuals.Count; j++) {
+              similarityMatrix[i][j] = CalculateSolutionSimilarity(individuals[i], individuals[j]);
+              if (i == j) continue;
+              similarityMatrix[j][i] = CalculateSolutionSimilarity(individuals[j], individuals[i]);
+            }
+          });
+        }
+      } else {
+        if (IsCommutative) {
+          for (int i = 0; i < individuals.Count; i++) {
+            for (int j = i; j < individuals.Count; j++) {
+              similarityMatrix[i][j] =
+                similarityMatrix[j][i] = CalculateSolutionSimilarity(individuals[i], individuals[j]);
+            }
           }
-        }
-      } else {
-        for (int i = 0; i < individuals.Count; i++) {
-          for (int j = i; j < individuals.Count; j++) {
-            similarityMatrix[i][j] = CalculateSolutionSimilarity(individuals[i], individuals[j]);
-            if (i == j) continue;
-            similarityMatrix[j][i] = CalculateSolutionSimilarity(individuals[j], individuals[i]);
+        } else {
+          for (int i = 0; i < individuals.Count; i++) {
+            for (int j = i; j < individuals.Count; j++) {
+              similarityMatrix[i][j] = CalculateSolutionSimilarity(individuals[i], individuals[j]);
+              if (i == j) continue;
+              similarityMatrix[j][i] = CalculateSolutionSimilarity(individuals[j], individuals[i]);
+            }
           }
         }
