I apologize ahead of time for the length of this question...It's a little involved. I am writing a 'weighted sum' operation that's pretty simple; take n images, multiply each image by a specific multiplier and sum them into an output image (by iterating through each pixel). When the number of images is constant, I can hardcode the logic into one iteration, however, I wish to make the method flexible enough to handle a variable number of images. I cannot come up with an equally 'performant' way to accomplish this, e.g. without an additional inner loop when the number of inputs is unknown. Here's my situation:
var rnd = new Random();
//Pixels in input and output images
const int x = 1000000;
//An output composite image
var pixelmap = new int[x];
var tStart = DateTime.Now;
//Known number of inputs
int knownNumberOfInputs = 3;
//Weights to apply to each pixel of the input images
//multipliers[0] applies to all pixels of inputA,
//multipliers[1] applies to all pixels of inputB etc.
var multipliers = new byte[3];
rnd.NextBytes(multipliers);
/* situation 1
* - I know how many input images
* - Arrays are independent */
//3 (knownNumberOfInputs) input images (we'll use random numbers for filler)
var inputA = new byte[x];
rnd.NextBytes(inputA);
var inputB = new byte[x];
rnd.NextBytes(inputB);
var inputC = new byte[x];
rnd.NextBytes(inputC);
//I can iterate through each pixel of each input image, multiply and sum for pixelmap value.
//Without a nested loop
for (var i = 0; i < x; i++)
{
pixelmap[i] = (
(inputA[i]*multipliers[0]) +
(inputB[i]*multipliers[1]) +
(inputC[i]*multipliers[2])
);
}
Console.WriteLine("Operation took " + DateTime.Now.Subtract(tStart).TotalMilliseconds + " ms");
// Operation took 39 ms
tStart = DateTime.Now;
/* situation 2
* unknown number of inputs
* inputs are contained within jagged array */
/* Caveat - multipliers.Length == inputs.Length */
//var unknownNumberOfInputs = rnd.Next(1, 10);
var unknownNumberOfInputs = 3; //Just happens to be the same number (for performance comparisons)
multipliers = new byte[unknownNumberOfInputs];
rnd.NextBytes(multipliers);
//Jagged array to contain input images
var inputs = new byte[unknownNumberOfInputs][];
//Load unknownNumberOfInputs of input images into jagged array
for (var i = 0; i < unknownNumberOfInputs; i++)
{
inputs[i] = new byte[x];
rnd.NextBytes(inputs[i]);
}
// I cannot iterate through each pixel of each input image
// Inner nested loop
for (var i = 0; i < x; i++)
{
for (var t=0;t<multipliers.Length;t++)
{
pixelmap[i] += (inputs[t][i] * multipliers[t]);
}
}
Console.WriteLine("Operation took " + DateTime.Now.Subtract(tStart).TotalMilliseconds + " ms");
//Operation took 54 ms
//How can I get rid of the inner nested loop and gain the performance of LoopA?
//Or is that the cost of not knowing?
Big ups
A little more info
- The pixelmap is going into a WriteableBitmap in Silverlight - which, once constructed, takes a 1D array as a pixel source (since height/width is passed into the constructor)
- Each input image has a specific multiplier, e.g. multiply all the pixels of input 1 by 2, all the pixels of input 2 by 3 etc.
- There will never be more than 20 inputs.
Stopwatchclass instead ofDateTime