I have a list of 3D X/Y/Z points, foundPoints and single 3D X/Y/Z point, rayOrigin. I'm looking to return the point from the list that is farthest from rayOrigin. It is likely that the list could contain several thousand points so I had wanted to multithread it.
I have an existing single thread function that works fine and is O(n). The first attempt I've made at multithreading is O(2n) because I'm going through the lists twice, I fully admit it isn't pretty but I'm struggling to find a way to do this with multiple threads but in O(n). I suspect the answer will be something with PLINQ but I'm very much open to suggestions.
Here's my single thread code
static List<double> getFarthestPoint(List<List<double>> foundPoints, double[] rayOrigin)
{
//No need to iterate if we have one point
if (foundPoints.Count == 1)
{
return foundPoints[0];
}
//Run through a bunch of output points and compare to eyePoin
List<double> farthestPoint = foundPoints[0];
double maxDistance = getPointDistance(rayOrigin, farthestPoint);
double pointDistance;
foreach (List<double> foundPoint in foundPoints)
{
pointDistance = getPointDistance(rayOrigin, foundPoint);
if (pointDistance > maxDistance)
{
maxDistance = pointDistance;
farthestPoint = foundPoint;
}
}
//Return max distance point
return farthestPoint;
}
And here's my mediocre multithreaded code
static List<double> getFarthestPointMultiThread(List<List<double>> foundPoints, double[] rayOrigin)
{
//No need to iterate if we have one point
if (foundPoints.Count == 1)
{
return foundPoints[0];
}
//This is multi-threaded but still O(2n) is there a way to multi-thread an O(n)?
Dictionary<Double, List<Double>> calculatedDistances = new Dictionary<double, List<double>>();
//Multi thread to create dictionary of all distances
Parallel.For(0, foundPoints.Count, i =>
calculatedDistances.Add(getPointDistance(rayOrigin, foundPoints[i]), foundPoints[i]));
//return point of max distance
return calculatedDistances[calculatedDistances.Keys.AsParallel().Max()];
}
I'm not all that familiar with PLINQ, but this call chain should allow you to distribute the workload:
Thanks to @PeterDuniho for pointing out a major flaw in my previous benchmark setup.
Here are the results (20 million points, 100 iterations, running on an i7-3820 @ 3.6 GHz):
Test code: