public IEnumerable <Fix64> ParallelizedCalculateIntegerSumUpToNumbers(int[] numbers) { if (numbers.Length != MaxDegreeOfParallelism) { throw new ArgumentException( "Provide as many numbers as the degree of parallelism of Fix64Calculator is (" + MaxDegreeOfParallelism + ")"); } var memory = new SimpleMemory(2 * MaxDegreeOfParallelism); for (int i = 0; i < numbers.Length; i++) { memory.WriteInt32(ParallelizedCalculateLargeIntegerSum_Int32NumbersStartIndex + i, numbers[i]); } ParallelizedCalculateIntegerSumUpToNumbers(memory); var results = new Fix64[MaxDegreeOfParallelism]; for (int i = 0; i < MaxDegreeOfParallelism; i++) { var itemOutputStartIndex = ParallelizedCalculateLargeIntegerSum_OutputInt32sStartIndex + i * 2; results[i] = Fix64.FromRawInts(new[] { memory.ReadInt32(itemOutputStartIndex), memory.ReadInt32(itemOutputStartIndex + 1) }); } return(results); }
public virtual void IsPrimeNumber(SimpleMemory memory) { var number = memory.ReadUInt32(IsPrimeNumber_InputUInt32Index); var isPrime = IsPrimeNumberInternal(number); memory.WriteBoolean(IsPrimeNumber_OutputBooleanIndex, isPrime); }
private int[] RunSimdOperation(int[] vector1, int[] vector2, Action <SimpleMemory> operation) { SimdOperations.ThrowIfVectorsNotEquallyLong(vector1, vector2); var originalElementCount = vector1.Length; vector1 = vector1.PadToMultipleOf(MaxDegreeOfParallelism); vector2 = vector2.PadToMultipleOf(MaxDegreeOfParallelism); var elementCount = vector1.Length; var memory = new SimpleMemory(1 + elementCount * 2); memory.WriteInt32(VectorsElementCountInt32Index, elementCount); for (int i = 0; i < elementCount; i++) { memory.WriteInt32(VectorElementsStartInt32Index + i, vector1[i]); memory.WriteInt32(VectorElementsStartInt32Index + elementCount + i, vector2[i]); } operation(memory); var result = new int[elementCount]; for (int i = 0; i < elementCount; i++) { result[i] = memory.ReadInt32(ResultVectorElementsStartInt32Index + i); } return(result.CutToLength(originalElementCount)); }
/// <summary> /// Calculates whether the number is prime, in an async way. /// </summary> /// <remarks> /// For efficient parallel execution with multiple connected FPGA boards you can make a non-parallelized hardware /// entry point method async like this. /// </remarks> public virtual Task IsPrimeNumberAsync(SimpleMemory memory) { IsPrimeNumber(memory); // In .NET <4.6 Task.FromResult(true) can be used too. return(Task.CompletedTask); }
/// <summary> /// 初始化 /// </summary> private SimpleMediator() { //系统实例化 CampSystem = new SimpleCamp(); MemorySystem = new SimpleMemory(); GameMgr = new SimpleGameMgr(); }
private static void Verify(SimpleMemory memory, SimpleMemory referenceMemory) { var mismatches = new List <HardwareExecutionResultMismatchException.Mismatch>(); for (int i = 0; i < memory.CellCount && i < referenceMemory.CellCount; i++) { if (!memory.Read4Bytes(i).SequenceEqual(referenceMemory.Read4Bytes(i))) { mismatches.Add(new HardwareExecutionResultMismatchException.Mismatch( i, memory.Read4Bytes(i), referenceMemory.Read4Bytes(i))); } } if (mismatches.Count > 0) { Console.WriteLine("MISMATCH:"); Console.WriteLine(new HardwareExecutionResultMismatchException(mismatches)); } if (memory.CellCount != referenceMemory.CellCount) { Console.WriteLine("MISMATCH IN LENGTH:{0}Hardware: {1}{0}Software: {2}", Environment.NewLine, memory.CellCount, referenceMemory.CellCount); } else if (mismatches.Count == 0) { Console.WriteLine("Verification passed!"); } }
/// <summary> /// Calculates for multiple numbers whether they're primes, in a parallelized way. /// </summary> /// <remarks> /// This demonstrates how you can write parallelized code that Hastlayer will process and turn into hardware-level /// parallelization: the Tasks' bodies will be copied in hardware as many times as many Tasks you start; thus, /// the actual level of parallelism you get on the hardware corresponds to the number of Tasks, not the number /// of CPU cores. /// </remarks> public virtual void ParallelizedArePrimeNumbers(SimpleMemory memory) { // We need this information explicitly as we can't store arrays directly in memory. uint numberCount = memory.ReadUInt32(ArePrimeNumbers_InputUInt32CountIndex); // At the moment Hastlayer only supports a fixed degree of parallelism so we need to pad the input array // if necessary, see PrimeCalculatorExtensions. var tasks = new Task <bool> [MaxDegreeOfParallelism]; int i = 0; while (i < numberCount) { for (int m = 0; m < MaxDegreeOfParallelism; m++) { var currentNumber = memory.ReadUInt32(ArePrimeNumbers_InputUInt32sStartIndex + i + m); // Note that you can just call (thread-safe) methods from inside Tasks as usual. In hardware those // invoked methods will be copied together with the Tasks' bodies too. tasks[m] = Task.Factory.StartNew( numberObject => IsPrimeNumberInternal((uint)numberObject), currentNumber); } // Hastlayer doesn't support async code at the moment since ILSpy doesn't handle the new Roslyn-compiled // code. See: https://github.com/icsharpcode/ILSpy/issues/502 Task.WhenAll(tasks).Wait(); for (int m = 0; m < MaxDegreeOfParallelism; m++) { memory.WriteBoolean(ArePrimeNumbers_OutputBooleansStartIndex + i + m, tasks[m].Result); } i += MaxDegreeOfParallelism; } }
/// <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); }
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 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); numberContainers1[2].IncreaseNumberBy10(); // Using ref and out. uint increaseBy = 10; numberContainers1[3].IncreaseNumberByParameterTimes10(ref increaseBy, out uint originalNumber);
public static uint CalculateFactorial(this RecursiveAlgorithms recursiveAlgorithms, short number) { var memory = new SimpleMemory(2); memory.WriteInt32(RecursiveAlgorithms.CalculateFactorial_InputShortIndex, number); recursiveAlgorithms.CalculateFactorial(memory); return(memory.ReadUInt32(RecursiveAlgorithms.CalculateFactorial_OutputUInt32Index)); }
public SimpleMemory GetMemory() { if (_memory == null) { _memory = new SimpleMemory(memsz); } return(_memory); }
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)); }
/// <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 int Run(int input) { var memory = new SimpleMemory(1); memory.WriteInt32(Run_InputOutputInt32Index, input); Run(memory); return(memory.ReadInt32(Run_InputOutputInt32Index)); }
public uint CalculateFactorial(short number) { var memory = new SimpleMemory(2); memory.WriteInt32(CalculateFactorial_InputShortIndex, number); CalculateFactorial(memory); return(memory.ReadUInt32(CalculateFactorial_OutputUInt32Index)); }
public uint Run(uint input) { var memory = new SimpleMemory(1); memory.WriteUInt32(Run_InputUInt32Index, input); Run(memory); return(memory.ReadUInt32(Run_OutputUInt32Index)); }
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)); }
public uint CalculateFibonacchiSeries(short number) { var memory = new SimpleMemory(2); memory.WriteInt32(CalculateFibonacchiSeries_InputShortIndex, number); CalculateFibonacchiSeries(memory); return(memory.ReadUInt32(CalculateFibonacchiSeries_OutputUInt32Index)); }
/// <summary> /// Calculates whether a number is prime. /// </summary> /// <remarks> /// Note that the entry point of SimpleMemory-using algorithms should be void methods having a single /// <see cref="SimpleMemory"/> argument. /// </remarks> /// <param name="memory">The <see cref="SimpleMemory"/> object representing the accessible memory space.</param> public virtual void IsPrimeNumber(SimpleMemory memory) { // Reading out the input parameter. var number = memory.ReadUInt32(IsPrimeNumber_InputUInt32Index); // Writing back the output. memory.WriteBoolean(IsPrimeNumber_OutputBooleanIndex, IsPrimeNumberInternal(number)); }
public static int Run(this Loopback loopback, int input) { var memory = new SimpleMemory(1); memory.WriteInt32(Loopback.Run_InputOutputInt32Index, input); loopback.Run(memory); return(memory.ReadInt32(Loopback.Run_InputOutputInt32Index)); }
public int Run(int startIndex, int length) { var memory = new SimpleMemory(startIndex + length < 2 ? 2 : startIndex + length); memory.WriteInt32(Run_StartIndexInt32Index, startIndex); memory.WriteInt32(Run_LengthInt32Index, length); Run(memory); return(memory.ReadInt32(Run_StartIndexInt32Index)); }
/// <summary> /// It loads the TestMode, NumberOfIterations parameters and also the PRNG seed from the SimpleMemory at /// the beginning. /// </summary> /// <param name="memory"></param> public void InitializeParametersFromMemory(SimpleMemory memory) { Prng1 = new PrngMWC64X((((ulong)memory.ReadUInt32(MemIndexRandomStates)) << 32) | memory.ReadUInt32(MemIndexRandomStates + 1)); Prng2 = new PrngMWC64X((((ulong)memory.ReadUInt32(MemIndexRandomStates + 2)) << 32) | memory.ReadUInt32(MemIndexRandomStates + 3)); TestMode = (memory.ReadUInt32(MemIndexStepMode) & 1) == 1; NumberOfIterations = memory.ReadUInt32(MemIndexNumberOfIterations); }
public virtual Task IsPrimeNumberAsync(SimpleMemory memory) { IsPrimeNumber(memory); // For efficient parallel execution with multiple connected FPGA boards you can make a non-parallelized // hardware entry point method async with Task.FromResult(). In .NET <4.6 Task.FromResult(true) can be used // too. return(Task.CompletedTask); }
/// <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)); }
/// <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); }
/// <summary>Pull table from the FPGA.</summary> public static void CopyFromSimpleMemoryToGrid(KpzNode[,] gridDst, SimpleMemory memorySrc) { for (int x = 0; x < KpzKernels.GridWidth; x++) { for (int y = 0; y < KpzKernels.GridHeight; y++) { gridDst[x, y] = KpzNode.DeserializeFromUInt32(memorySrc.ReadUInt32(KpzKernels.MemIndexGrid + y * KpzKernels.GridWidth + x)); } } }
private static void SaveFile(OutputFileType fileType, PayloadType payloadType, string fileName, bool isInput, SimpleMemory memory) { var fileNamePrefix = isInput ? "in-" : "out-"; var direction = isInput ? "input" : "output"; switch (fileType) { case OutputFileType.None: return; case OutputFileType.Hexdump: if (string.IsNullOrEmpty(fileName)) { fileName = fileNamePrefix + DefaultHexdumpFileName; } Console.WriteLine("Saving {0} hexdump to '{1}'...", direction, fileName); if (fileName == Options.OutputFileNameConsole) { WriteHexdump(Console.Out, memory); } else { using (var streamWriter = new StreamWriter(fileName, false, Encoding.UTF8)) { WriteHexdump(streamWriter, memory); } } break; case OutputFileType.Binary: if (payloadType != PayloadType.BinaryFile) { if (string.IsNullOrEmpty(fileName)) { fileName = fileNamePrefix + DefaultBinaryFileName; } Console.WriteLine("Saving {0} binary file to '{1}'...", direction, fileName); using (var fileStream = File.OpenWrite(fileName)) { var accessor = new SimpleMemoryAccessor(memory); var segment = accessor.Get().GetUnderlyingArray(); fileStream.Write(segment.Array, segment.Offset, memory.ByteCount); } } break; default: throw new ArgumentException(string.Format("Unknown {0} file type: {1}", direction, fileType)); } Console.WriteLine("File saved."); }
/// <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)); } } }