/// <summary> /// Creates a <see cref="SimpleMemory"/> instance that stores the image. /// </summary> /// <param name="image">The image to process.</param> /// <param name="contrastValue">The contrast difference value.</param> /// <returns>The instance of the created <see cref="SimpleMemory"/>.</returns> private SimpleMemory CreateSimpleMemory(Bitmap image, int contrastValue) { var pixelCount = image.Width * image.Height; var cellCount = pixelCount + (pixelCount % MaxDegreeOfParallelism != 0 ? MaxDegreeOfParallelism : 0) + 3; var memory = new SimpleMemory(cellCount); memory.WriteUInt32(ChangeContrast_ImageWidthIndex, (uint)image.Width); memory.WriteUInt32(ChangeContrast_ImageHeightIndex, (uint)image.Height); memory.WriteInt32(ChangeContrast_ContrastValueIndex, contrastValue); for (int x = 0; x < image.Height; x++) { for (int y = 0; y < image.Width; y++) { var pixel = image.GetPixel(y, x); // This leaves 1 byte unused in each memory cell, but that would make the whole logic a lot more // complicated, so good enough for a sample; if we'd want to optimize memory usage, that would be // needed. memory.Write4Bytes( x * image.Width + y + ChangeContrast_ImageStartIndex, new[] { pixel.R, pixel.G, pixel.B }); } } return(memory); }
/// <summary> /// This copies random seed from the host to the FPGA. /// </summary> public static SimpleMemory PushRandomSeed(this PrngTestInterface kernels, ulong seed) { SimpleMemory sm = new SimpleMemory(3); sm.WriteUInt32(0, (uint)seed); //LE: 0 is low byte, 1 is high byte sm.WriteUInt32(1, (uint)(seed >> 32)); return(sm); }
public virtual void CalculateFactorial(SimpleMemory memory) { memory.WriteUInt32(CalculateFactorial_InvocationCounterUInt32Index, 1); var number = (short)memory.ReadInt32(CalculateFactorial_InputShortIndex); memory.WriteUInt32(CalculateFactorial_OutputUInt32Index, RecursivelyCalculateFactorial(memory, number)); }
/// <summary> /// This function adds two numbers on the FPGA using <see cref="KpzKernelsInterface.TestAdd(SimpleMemory)"/>. /// </summary> public static uint TestAddWrapper(this KpzKernelsInterface kernels, uint a, uint b) { var sm = new SimpleMemory(3); sm.WriteUInt32(0, a); sm.WriteUInt32(1, b); kernels.TestAdd(sm); return(sm.ReadUInt32(2)); }
public virtual void MWC64X(SimpleMemory memory) { uint stateHighWord = memory.ReadUInt32(1); uint stateLowWord = memory.ReadUInt32(0);; ulong randomState = stateLowWord * 0xFFFEB81BUL + stateHighWord; uint randomWord = stateLowWord ^ stateHighWord; memory.WriteUInt32(0, (uint)randomState); //LE: 1 is high byte, 0 is low byte memory.WriteUInt32(1, (uint)(randomState >> 32)); memory.WriteUInt32(2, randomWord); }
public virtual void MWC64X(SimpleMemory memory) { uint stateHighWord = memory.ReadUInt32(1); uint stateLowWord = memory.ReadUInt32(0);; // Creating the value 0xFFFEB81BUL. This literal can't be directly used due to an ILSpy bug, see: // https://github.com/icsharpcode/ILSpy/issues/807 uint constantHighShort = 0xFFFE; uint constantLowShort = 0xB81B; uint constantWord = (0 << 32) | (constantHighShort << 16) | constantLowShort; ulong randomState = (ulong)stateLowWord * (ulong)constantWord + (ulong)stateHighWord; uint randomWord = stateLowWord ^ stateHighWord; memory.WriteUInt32(0, (uint)randomState); //LE: 1 is high byte, 0 is low byte memory.WriteUInt32(1, (uint)(randomState >> 32)); memory.WriteUInt32(2, randomWord); }
public static uint Run(this ParallelAlgorithm algorithm, uint input) { var memory = new SimpleMemory(1); memory.WriteUInt32(ParallelAlgorithm.Run_InputUInt32Index, input); algorithm.Run(memory); return memory.ReadUInt32(ParallelAlgorithm.Run_OutputUInt32Index); }
public static uint Run(this ObjectOrientedShowcase algorithm, uint input) { var memory = new SimpleMemory(1); memory.WriteUInt32(ObjectOrientedShowcase.Run_InputUInt32Index, input); algorithm.Run(memory); return(memory.ReadUInt32(ObjectOrientedShowcase.Run_OutputUInt32Index)); }
public static bool IsPrimeNumber(this PrimeCalculator primeCalculator, uint number) { var memory = new SimpleMemory(1); memory.WriteUInt32(PrimeCalculator.IsPrimeNumber_InputUInt32Index, number); primeCalculator.IsPrimeNumber(memory); return(memory.ReadBoolean(PrimeCalculator.IsPrimeNumber_OutputBooleanIndex)); }
public uint Run(uint input) { var memory = new SimpleMemory(1); memory.WriteUInt32(Run_InputUInt32Index, input); Run(memory); return(memory.ReadUInt32(Run_OutputUInt32Index)); }
public double EstimatePi(uint iterationsCount) { if (iterationsCount % MaxDegreeOfParallelism != 0) { throw new Exception($"The number of iterations must be divisible by {MaxDegreeOfParallelism}."); } var memory = new SimpleMemory(2); memory.WriteUInt32(EstimatePi_IteractionsCountUInt32Index, iterationsCount); memory.WriteUInt32(EstimatePi_RandomSeedUInt32Index, (uint)_random.Next(0, int.MaxValue)); EstimatePi(memory); // This single calculation takes up too much space on the FPGA, since it needs fix point arithmetic, but // it doesn't take much time. So doing it on the host instead. return((double)memory.ReadInt32(EstimatePi_InCircleCountSumUInt32Index) / iterationsCount * 4); }
/// <summary> /// Makes the changes according to the matrix on the image. /// </summary> /// <param name="memory">The <see cref="SimpleMemory"/> object representing the accessible memory space.</param> public virtual void FilterImage(SimpleMemory memory) { ushort imageWidth = (ushort)memory.ReadUInt32(FilterImage_ImageWidthIndex); ushort imageHeight = (ushort)memory.ReadUInt32(FilterImage_ImageHeightIndex); int factor = memory.ReadInt32(FilterImage_FactorIndex); int offset = memory.ReadInt32(FilterImage_OffsetIndex); int topLeftValue = memory.ReadInt32(FilterImage_TopLeftIndex); int topMiddleValue = memory.ReadInt32(FilterImage_TopMiddleIndex); int topRightValue = memory.ReadInt32(FilterImage_TopRightIndex); int middleLeftValue = memory.ReadInt32(FilterImage_MiddleLeftIndex); int pixelValue = memory.ReadInt32(FilterImage_PixelIndex); int middleRightValue = memory.ReadInt32(FilterImage_MiddleRightIndex); int bottomLeftValue = memory.ReadInt32(FilterImage_BottomLeftIndex); int bottomMiddleValue = memory.ReadInt32(FilterImage_BottomMiddleIndex); int bottomRightValue = memory.ReadInt32(FilterImage_BottomRightIndex); ushort topLeft = 0; ushort topMiddle = 0; ushort topRight = 0; ushort middleLeft = 0; ushort pixel = 0; ushort middleRight = 0; ushort bottomLeft = 0; ushort bottomMiddle = 0; ushort bottomRight = 0; int pixelCountHelper = imageHeight * imageWidth * 3; ushort imageWidthHelper = (ushort)(imageWidth * 3); for (int x = 1; x < imageHeight - 1; x++) { for (int y = 3; y < imageWidthHelper - 3; y++) { topLeft = (ushort)memory.ReadUInt32(x * imageWidthHelper + y + pixelCountHelper - imageWidthHelper - 3 + FilterImage_ImageStartIndex); topMiddle = (ushort)memory.ReadUInt32(x * imageWidthHelper + y + pixelCountHelper - imageWidthHelper + FilterImage_ImageStartIndex); topRight = (ushort)memory.ReadUInt32(x * imageWidthHelper + y + pixelCountHelper - imageWidthHelper + 3 + FilterImage_ImageStartIndex); middleLeft = (ushort)memory.ReadUInt32(x * imageWidthHelper + y + pixelCountHelper - 3 + FilterImage_ImageStartIndex); pixel = (ushort)memory.ReadUInt32(x * imageWidthHelper + y + pixelCountHelper + FilterImage_ImageStartIndex); middleRight = (ushort)memory.ReadUInt32(x * imageWidthHelper + y + pixelCountHelper + 3 + FilterImage_ImageStartIndex); bottomLeft = (ushort)memory.ReadUInt32(x * imageWidthHelper + y + pixelCountHelper + imageWidthHelper - 3 + FilterImage_ImageStartIndex); bottomMiddle = (ushort)memory.ReadUInt32(x * imageWidthHelper + y + pixelCountHelper + imageWidthHelper + FilterImage_ImageStartIndex); bottomRight = (ushort)memory.ReadUInt32(x * imageWidthHelper + y + pixelCountHelper + imageWidthHelper + 3 + FilterImage_ImageStartIndex); memory.WriteUInt32(x * imageWidthHelper + y + FilterImage_ImageStartIndex, CalculatePixelValue( topLeft, topMiddle, topRight, middleLeft, pixel, middleRight, bottomLeft, bottomMiddle, bottomRight, topLeftValue, topMiddleValue, topRightValue, middleLeftValue, pixelValue, middleRightValue, bottomLeftValue, bottomMiddleValue, bottomRightValue, factor, offset)); } } }
/// <summary>Push table into FPGA.</summary> public static void CopyFromGridToSimpleMemory(KpzNode[,] gridSrc, SimpleMemory memoryDst) { for (int x = 0; x < KpzKernels.GridHeight; x++) { for (int y = 0; y < KpzKernels.GridWidth; y++) { KpzNode node = gridSrc[x, y]; memoryDst.WriteUInt32(KpzKernels.MemIndexGrid + y * KpzKernels.GridWidth + x, node.SerializeToUInt32()); } } }
/// <summary> /// Copies the grid data from BRAM/LUT RAM to DDR. /// </summary> public void CopyToSimpleMemoryFromRawGrid(SimpleMemory memory) { for (int y = 0; y < GridHeight; y++) { for (int x = 0; x < GridWidth; x++) { int index = y * GridWidth + x; memory.WriteUInt32(MemIndexGrid + index, _gridRaw[index]); } } }
/// <summary>Push table into FPGA.</summary> public static void CopyFromGridToSimpleMemory(KpzNode[,] gridSrc, SimpleMemory memoryDst) { for (int x = 0; x < KpzKernelsParallelizedInterface.GridSize; x++) { for (int y = 0; y < KpzKernelsParallelizedInterface.GridSize; y++) { KpzNode node = gridSrc[x, y]; memoryDst.WriteUInt32(KpzKernelsParallelizedInterface.MemIndexGrid + y * KpzKernelsParallelizedInterface.GridSize + x, node.SerializeToUInt32()); } } }
private static async Task <bool> RunIsPrimeNumber(uint number, Func <SimpleMemory, Task> methodRunner) { // One memory cell is enough for data exchange. var memory = new SimpleMemory(1); memory.WriteUInt32(PrimeCalculator.IsPrimeNumber_InputUInt32Index, number); await methodRunner(memory); return(memory.ReadBoolean(PrimeCalculator.IsPrimeNumber_OutputBooleanIndex)); }
public virtual void EstimatePi(SimpleMemory memory) { var iterationsCount = memory.ReadUInt32(EstimatePi_IteractionsCountUInt32Index); var randomSeed = (ushort)memory.ReadUInt32(EstimatePi_RandomSeedUInt32Index); var iterationsPerTask = iterationsCount / MaxDegreeOfParallelism; var tasks = new Task <uint> [MaxDegreeOfParallelism]; for (uint i = 0; i < MaxDegreeOfParallelism; i++) { tasks[i] = Task.Factory.StartNew( indexObject => { var index = (uint)indexObject; // A 16b PRNG is enough for this task and the xorshift one has suitable quality. var random = new RandomXorshiftLfsr16 { State = (ushort)(randomSeed + index) }; uint inCircleCount = 0; for (var j = 0; j < iterationsPerTask; j++) { uint a = random.NextUInt16(); uint b = random.NextUInt16(); // A bit of further parallelization can be exploited with SIMD to shave off some execution // time. However, this needs so much resources on the hardware that the degree of // parallelism needs to be lowered substantially (below 60). //var randomNumbers = new uint[] { random.NextUInt16(), random.NextUInt16() }; //var products = Common.Numerics.SimdOperations.MultiplyVectors(randomNumbers, randomNumbers, 2); if ((ulong)(a * a) + b * b <= ((uint)ushort.MaxValue * ushort.MaxValue)) //if ((ulong)products[0] + products[1] <= ((uint)ushort.MaxValue * ushort.MaxValue)) { inCircleCount++; } } return(inCircleCount); }, i); } Task.WhenAll(tasks).Wait(); uint inCircleCountSum = 0; for (int i = 0; i < MaxDegreeOfParallelism; i++) { inCircleCountSum += tasks[i].Result; } memory.WriteUInt32(EstimatePi_InCircleCountSumUInt32Index, inCircleCountSum); }
private uint RecursivelyCalculateFactorial(SimpleMemory memory, short number) { memory.WriteUInt32( CalculateFactorial_InvocationCounterUInt32Index, memory.ReadUInt32(CalculateFactorial_InvocationCounterUInt32Index) + 1); if (number == 0) { return(1); } return((uint)(number * RecursivelyCalculateFactorial(memory, (short)(number - 1)))); }
// The return value should be a type with a bigger range than the input. Although we can use 64b numbers // internally we can't write the to memory yet so the input needs to be a short. private uint RecursivelyCalculateFibonacchiSeries(SimpleMemory memory, short number) { memory.WriteUInt32( CalculateFibonacchiSeries_InvocationCounterUInt32Index, memory.ReadUInt32(CalculateFibonacchiSeries_InvocationCounterUInt32Index) + 1); if (number == 0 || number == 1) { return((uint)number); } return(RecursivelyCalculateFibonacchiSeries(memory, (short)(number - 2)) + RecursivelyCalculateFibonacchiSeries(memory, (short)(number - 1))); }
/// <summary> /// This function is for testing how Hastlayer works by running a random generator, writing the results into /// SimpleMemory. /// </summary> public void TestPrng(SimpleMemory memory) { var kernels = new KpzKernels(); kernels.InitializeParametersFromMemory(memory); var numberOfStepsInIteration = KpzKernels.GridWidth * KpzKernels.GridHeight; for (int i = 0; i < numberOfStepsInIteration; i++) { memory.WriteUInt32(i, kernels.Random1.NextUInt32()); } }
/// <summary> /// Creates a <see cref="SimpleMemory"/> object filled with the input values. /// </summary> /// <param name="inputOne">The first string to compare.</param> /// <param name="inputTwo">The second string to compare.</param> /// <returns>Returns a <see cref="SimpleMemory"/> object containing the input values.</returns> private SimpleMemory CreateSimpleMemory(string inputOne, string inputTwo) { var cellCount = 2 + inputOne.Length + inputTwo.Length + (inputOne.Length * inputTwo.Length) * 2 + Math.Max(inputOne.Length, inputTwo.Length); var simpleMemory = new SimpleMemory(cellCount); simpleMemory.WriteUInt32(GetLCS_InputOneLengthIndex, (uint)inputOne.Length); simpleMemory.WriteUInt32(GetLCS_InputTwoLengthIndex, (uint)inputTwo.Length); for (int i = 0; i < inputOne.Length; i++) { simpleMemory.WriteUInt32(GetLCS_InputOneStartIndex + i, Encoding.UTF8.GetBytes(inputOne[i].ToString())[0]); } for (int i = 0; i < inputTwo.Length; i++) { simpleMemory.WriteUInt32(GetLCS_InputOneStartIndex + i + inputOne.Length, Encoding.UTF8.GetBytes(inputTwo[i].ToString())[0]); } return(simpleMemory); }
/// <summary> /// Creates a <see cref="SimpleMemory"/> object filled with the input values. /// </summary> /// <param name="iterationsCount">The number of iterations the algorithm uses for calculations.</param> /// <returns>Returns a <see cref="SimpleMemory"/> object containing the input values.</returns> private static SimpleMemory CreateSimpleMemory(int iterationsCount) { var simpleMemory = new SimpleMemory(10 + iterationsCount * 3); simpleMemory.WriteInt32(MonteCarloAlgorithm.MonteCarloAlgorithm_IterationsCountIndex, iterationsCount); for (int i = 0; i < iterationsCount * 3; i++) { simpleMemory.WriteUInt32(MonteCarloAlgorithm.MonteCarloAlgorithm_RandomNumbersStartIndex + i, (uint)(_random.Next(101))); } return(simpleMemory); }
public static bool[] ArePrimeNumbers(this PrimeCalculator primeCalculator, uint[] numbers) { var memory = new SimpleMemory(numbers.Length + 1); memory.WriteUInt32(PrimeCalculator.ArePrimeNumbers_InputUInt32CountIndex, (uint)numbers.Length); for (int i = 0; i < numbers.Length; i++) { memory.WriteUInt32(PrimeCalculator.ArePrimeNumbers_InputUInt32sStartIndex + i, numbers[i]); } primeCalculator.ArePrimeNumbers(memory); var output = new bool[numbers.Length]; for (int i = 0; i < numbers.Length; i++) { output[i] = memory.ReadBoolean(PrimeCalculator.ArePrimeNumbers_OutputUInt32sStartIndex + i); } return(output); }
private static bool[] RunArePrimeNumbersMethod(uint[] numbers, Action <SimpleMemory> methodRunner) { // We need to allocate more memory cells, enough for all the inputs and outputs. var memory = new SimpleMemory(numbers.Length + 1); memory.WriteUInt32(PrimeCalculator.ArePrimeNumbers_InputUInt32CountIndex, (uint)numbers.Length); for (int i = 0; i < numbers.Length; i++) { memory.WriteUInt32(PrimeCalculator.ArePrimeNumbers_InputUInt32sStartIndex + i, numbers[i]); } methodRunner(memory); var output = new bool[numbers.Length]; for (int i = 0; i < numbers.Length; i++) { output[i] = memory.ReadBoolean(PrimeCalculator.ArePrimeNumbers_OutputBooleansStartIndex + i); } return(output); }
public virtual void Run(SimpleMemory memory) { var inputNumber = memory.ReadUInt32(Run_InputUInt32Index); // Or: inputNumber = new MemoryContainer(memory).GetInput(); // Arrays can be initialized as usual, as well as objects. var numberContainers1 = new[] { new NumberContainer { Number = inputNumber }, new NumberContainer { Number = inputNumber + 4 }, new NumberContainer { Number = 24 }, new NumberContainer(9) }; // Array elements can be accessed and modified as usual. numberContainers1[0].NumberPlusFive = inputNumber + 10; numberContainers1[1].IncreaseNumber(5); // Note that array dimensions need to be defined compile-time. They needn't bee constants directly used // when instantiating the array but the size argument needs to be resolvable compile-time (so if it's a // variable then its value should be computable from all other values at compile-time). var numberContainers2 = new NumberContainer[1]; var numberContainer = new NumberContainer(); numberContainer.Number = 5; numberContainer.Number = numberContainer.NumberPlusFive; if (!numberContainer.WasIncreased) { numberContainer.IncreaseNumber(5); } numberContainers2[0] = numberContainer; for (int i = 0; i < numberContainers1.Length; i++) { numberContainers1[i].IncreaseNumber(numberContainers2[0].Number); } // You can also pass arrays and other objects around to other methods. memory.WriteUInt32(Run_OutputUInt32Index, SumNumberCointainers(numberContainers1)); }
/// <summary> /// This function pushes parameters and PRNG seed to the FPGA. /// </summary> /// <param name="memoryDst"></param> /// <param name="testMode"></param> /// <param name="randomSeed1"></param> /// <param name="randomSeed2"></param> /// <param name="numberOfIterations"></param> public static void CopyParametersToMemory(SimpleMemory memoryDst, bool testMode, ulong randomSeed1, ulong randomSeed2, uint numberOfIterations) { memoryDst.WriteUInt32(KpzKernels.MemIndexRandomStates, (uint)(randomSeed1 & 0xFFFFFFFFUL)); memoryDst.WriteUInt32(KpzKernels.MemIndexRandomStates + 1, (uint)((randomSeed1 >> 32) & 0xFFFFFFFFUL)); memoryDst.WriteUInt32(KpzKernels.MemIndexRandomStates + 2, (uint)(randomSeed2 & 0xFFFFFFFFUL)); memoryDst.WriteUInt32(KpzKernels.MemIndexRandomStates + 3, (uint)((randomSeed2 >> 32) & 0xFFFFFFFFUL)); memoryDst.WriteUInt32(KpzKernels.MemIndexStepMode, (testMode) ? 1U : 0U); memoryDst.WriteUInt32(KpzKernels.MemIndexNumberOfIterations, numberOfIterations); }
public virtual void Run(SimpleMemory memory) { var input = memory.ReadUInt32(Run_InputUInt32Index); var tasks = new Task <uint> [MaxDegreeOfParallelism]; // Hastlayer will figure out how many Tasks you want to start if you kick them off in a loop like this. // If this is more involved then you'll need to tell Hastlayer the level of parallelism, see the comment in // ParallelAlgorithmSampleRunner. for (uint i = 0; i < MaxDegreeOfParallelism; i++) { tasks[i] = Task.Factory.StartNew( indexObject => { var index = (uint)indexObject; uint result = input + index * 2; var even = true; for (int j = 2; j < 9999999; j++) { if (even) { result += index; } else { result -= index; } even = !even; } return(result); }, i); } // Task.WhenAny() can be used too. Task.WhenAll(tasks).Wait(); uint output = 0; for (int i = 0; i < MaxDegreeOfParallelism; i++) { output += tasks[i].Result; } memory.WriteUInt32(Run_OutputUInt32Index, output); }
/// <summary> /// Creates a <see cref="SimpleMemory"/> instance that stores the image. /// </summary> /// <param name="image">The image to process.</param> /// <param name="topLeft">Top left value.</param> /// <param name="topMiddle">Top middle value.</param> /// <param name="topRight">Top right value.</param> /// <param name="middleLeft">Middle left value.</param> /// <param name="pixel">The current pixel value.</param> /// <param name="middleRight">Middle right value.</param> /// <param name="bottomLeft">Bottom left value.</param> /// <param name="bottomMiddle">Bottom middle value.</param> /// <param name="bottomRight">Bottom right value.</param> /// <param name="factor">The value to divide the summed matrix values with.</param> /// <param name="offset">Offset value added to the result.</param> /// <returns>The instance of the created <see cref="SimpleMemory"/>.</returns> private SimpleMemory CreateSimpleMemory( Bitmap image, int topLeft, int topMiddle, int topRight, int middleLeft, int pixel, int middleRight, int bottomLeft, int bottomMiddle, int bottomRight, int factor = 1, int offset = 0) { var memory = new SimpleMemory(image.Width * image.Height * 6 + 13); memory.WriteUInt32(FilterImage_ImageWidthIndex, (uint)image.Width); memory.WriteUInt32(FilterImage_ImageHeightIndex, (uint)image.Height); memory.WriteInt32(FilterImage_TopLeftIndex, topLeft); memory.WriteInt32(FilterImage_TopMiddleIndex, topMiddle); memory.WriteInt32(FilterImage_TopRightIndex, topRight); memory.WriteInt32(FilterImage_MiddleLeftIndex, middleLeft); memory.WriteInt32(FilterImage_PixelIndex, pixel); memory.WriteInt32(FilterImage_MiddleRightIndex, middleRight); memory.WriteInt32(FilterImage_BottomLeftIndex, bottomLeft); memory.WriteInt32(FilterImage_BottomMiddleIndex, bottomMiddle); memory.WriteInt32(FilterImage_BottomRightIndex, bottomRight); memory.WriteInt32(FilterImage_FactorIndex, factor); memory.WriteInt32(FilterImage_OffsetIndex, offset); int size = image.Width * image.Height; for (int x = 0; x < image.Height; x++) { for (int y = 0; y < image.Width; y++) { var pixelValue = image.GetPixel(y, x); memory.WriteUInt32((x * image.Width + y) * 3 + FilterImage_ImageStartIndex, pixelValue.R); memory.WriteUInt32((x * image.Width + y) * 3 + 1 + FilterImage_ImageStartIndex, pixelValue.G); memory.WriteUInt32((x * image.Width + y) * 3 + 2 + FilterImage_ImageStartIndex, pixelValue.B); memory.WriteUInt32((x * image.Width + y) * 3 + (size * 3) + FilterImage_ImageStartIndex, pixelValue.R); memory.WriteUInt32((x * image.Width + y) * 3 + 1 + (size * 3) + FilterImage_ImageStartIndex, pixelValue.G); memory.WriteUInt32((x * image.Width + y) * 3 + 2 + (size * 3) + FilterImage_ImageStartIndex, pixelValue.B); } } return(memory); }
public virtual void Run(SimpleMemory memory) { var input = memory.ReadUInt32(Run_InputUInt32Index); var tasks = new Task <uint> [MaxDegreeOfParallelism]; for (uint i = 0; i < MaxDegreeOfParallelism; i++) { tasks[i] = Task.Factory.StartNew( indexObject => { var index = (uint)indexObject; uint result = input + index * 2; var even = true; for (int j = 2; j < 9999999; j++) { if (even) { result += index; } else { result -= index; } even = !even; } return(result); }, i); } // Task.WhenAny() can be used too. Task.WhenAll(tasks).Wait(); uint output = 0; for (int i = 0; i < MaxDegreeOfParallelism; i++) { output += tasks[i].Result; } memory.WriteUInt32(Run_OutputUInt32Index, output); }
public virtual void CalculateTorusSectionValues(SimpleMemory memory) { int w, x, y, s, z, dw, dx, dy, dz, sw, swx, swy, swz, varw, varx, vary, varz, ss, volume; w = x = y = s = z = dw = dx = dy = dz = sw = swx = swy = swz = varw = varx = vary = varz = 0; // Rounded constant value instead of "0.2 * (Math.Exp(5.0) - Math.Exp(-5.0))". // This is the interval of s to be random sampled. ss = 29; volume = 3 * 7 * ss; // Volume of the sampled region in x,y,s space. int iterationsCount = memory.ReadInt32(MonteCarloAlgorithm_IterationsCountIndex); int sumsw = 0; int sumswx = 0; int sumswy = 0; int sumswz = 0; int sumvarw = 0; int sumvarwx = 0; int sumvarwy = 0; int sumvarwz = 0; uint randomX = 0; uint randomY = 0; uint randomZ = 0; for (int i = 1; i <= iterationsCount; i++) { randomX = memory.ReadUInt32(MonteCarloAlgorithm_RandomNumbersStartIndex + i); randomY = memory.ReadUInt32(MonteCarloAlgorithm_RandomNumbersStartIndex + i + 1); randomZ = memory.ReadUInt32(MonteCarloAlgorithm_RandomNumbersStartIndex + i + 2); // Pick points randomly from the sampled region. x = checked ((int)(Multiplier + randomX * 3 * Multiplier / 100)); // The constant can't be specified properly inline as (since it can't be specified as a short, see: // http://stackoverflow.com/questions/8670511/how-to-specify-a-short-int-constant-without-casting) // it would cause an underflow and be casted to an ulong. short minusThree = -3; y = checked ((int)(minusThree * Multiplier + randomY * 7 * Multiplier / 100)); short thirteen = 13; s = checked ((int)(thirteen + ss * (short)randomZ * Multiplier / 100)); short two = 2; z = checked ((int)(two * Multiplier * Log(5 * s / Multiplier) / 10)); int b = checked ((int)(Sqrt((x * x) + (y * y)) - 3 * Multiplier)); int a = checked ((int)(((z * z) + (b * b)) / Multiplier)); // Check if the selected points are inside the torus. // If they are inside, add to the various cumulants. if (a < Multiplier) { sw = checked (sw + Multiplier); swx = checked (swx + x); swy = checked (swy + y); swz = checked (swz + z); varw = Multiplier; varx += (x * x) / Multiplier; vary += (y * y) / Multiplier; varz += (z * z) / Multiplier; } // Divide the values with the multiplier to return to the original numbers in every 1000th iteration. // This way we can avoid overflows at the final computations, but we still get more precise values. if (i % 1000 == 0 || i == iterationsCount) { sumsw = checked (sumsw + sw / Multiplier); sumswx = checked (sumswx + swx / Multiplier); sumswy = checked (sumswy + swy / Multiplier); sumswz = checked (sumswz + swz / Multiplier); sumvarw = Multiplier; sumvarwx += varx / Multiplier; sumvarwy += vary / Multiplier; sumvarwz += varz / Multiplier; sw = swx = swy = swz = varw = varx = vary = varz = 0; } } // Values of the integrals. memory.WriteUInt32(MonteCarloAlgorithm_WIndex, checked ((uint)((uint)volume * (uint)sumsw / iterationsCount))); memory.WriteUInt32(MonteCarloAlgorithm_XIndex, checked ((uint)((uint)volume * (uint)sumswx / iterationsCount))); memory.WriteUInt32(MonteCarloAlgorithm_YIndex, checked ((uint)((uint)volume * (uint)sumswy / iterationsCount))); memory.WriteUInt32(MonteCarloAlgorithm_ZIndex, checked ((uint)((uint)volume * (uint)sumswz / iterationsCount))); // Values of the error estimates. memory.WriteUInt32(MonteCarloAlgorithm_DWIndex, checked ((uint)(volume * Sqrt((int)((sumvarw / iterationsCount - Pow((sumsw / iterationsCount), 2)) / iterationsCount))))); memory.WriteUInt32(MonteCarloAlgorithm_DXIndex, checked ((uint)(volume * Sqrt((int)((sumvarwx / iterationsCount - Pow((sumswx / iterationsCount), 2)) / iterationsCount))))); memory.WriteUInt32(MonteCarloAlgorithm_DYIndex, checked ((uint)(volume * Sqrt((int)((sumvarwy / iterationsCount - Pow((sumswy / iterationsCount), 2)) / iterationsCount))))); memory.WriteUInt32(MonteCarloAlgorithm_DZIndex, checked ((uint)(volume * Sqrt((int)((sumvarwz / iterationsCount - Pow((sumswz / iterationsCount), 2)) / iterationsCount))))); }