private void StartSolvingByDevice(Device.AMD device) { if (isStopSolving) { return; } Job nextJob = null, tempJob = null; var cpuThreadCount = 0; var edgeCount = new uint[1]; int[] edgeBuffer = new int[maxCpuHandleEdgeCount * 2]; var clearPattern = Marshal.AllocHGlobal(4); Marshal.Copy(new byte[4] { 0, 0, 0, 0 }, 0, clearPattern, 4); var maxLogLevel = (Level)Math.Max((int)MinimumLogLevel, (int)MinimumFileLogLevel); var timer = (maxLogLevel == Level.Verbose) ? new Stopwatch() : null; try { device.KernelSeedA.SetKernelArgument(0, device.BufferNonce); device.KernelSeedA.SetKernelArgument(1, device.BufferB); device.KernelSeedA.SetKernelArgument(2, device.BufferA1); device.KernelSeedA.SetKernelArgument(3, device.BufferI1); device.KernelSeedB1.SetKernelArgument(0, device.BufferA1); device.KernelSeedB1.SetKernelArgument(1, device.BufferA1); device.KernelSeedB1.SetKernelArgument(2, device.BufferA2); device.KernelSeedB1.SetKernelArgument(3, device.BufferI1); device.KernelSeedB1.SetKernelArgument(4, device.BufferI2); device.KernelSeedB1.SetKernelArgumentGeneric(5, (uint)32); device.KernelSeedB2.SetKernelArgument(0, device.BufferB); device.KernelSeedB2.SetKernelArgument(1, device.BufferA1); device.KernelSeedB2.SetKernelArgument(2, device.BufferA2); device.KernelSeedB2.SetKernelArgument(3, device.BufferI1); device.KernelSeedB2.SetKernelArgument(4, device.BufferI2); device.KernelSeedB2.SetKernelArgumentGeneric(5, (uint)0); device.KernelRound1.SetKernelArgument(0, device.BufferA1); device.KernelRound1.SetKernelArgument(1, device.BufferA2); device.KernelRound1.SetKernelArgument(2, device.BufferB); device.KernelRound1.SetKernelArgument(3, device.BufferI2); device.KernelRound1.SetKernelArgument(4, device.BufferI1); device.KernelRound1.SetKernelArgumentGeneric(5, (uint)Device.AMD.DUCK_SIZE_A * 1024); device.KernelRound1.SetKernelArgumentGeneric(6, (uint)Device.AMD.DUCK_SIZE_B * 1024); device.KernelRoundO.SetKernelArgument(0, device.BufferB); device.KernelRoundO.SetKernelArgument(1, device.BufferA1); device.KernelRoundO.SetKernelArgument(2, device.BufferI1); device.KernelRoundO.SetKernelArgument(3, device.BufferI2); device.KernelRoundNA.SetKernelArgument(0, device.BufferB); device.KernelRoundNA.SetKernelArgument(1, device.BufferA1); device.KernelRoundNA.SetKernelArgument(2, device.BufferI1); device.KernelRoundNA.SetKernelArgument(3, device.BufferI2); device.KernelRoundNB.SetKernelArgument(0, device.BufferA1); device.KernelRoundNB.SetKernelArgument(1, device.BufferB); device.KernelRoundNB.SetKernelArgument(2, device.BufferI2); device.KernelRoundNB.SetKernelArgument(3, device.BufferI1); device.KernelTail.SetKernelArgument(0, device.BufferB); device.KernelTail.SetKernelArgument(1, device.BufferA1); device.KernelTail.SetKernelArgument(2, device.BufferI1); device.KernelTail.SetKernelArgument(3, device.BufferI2); device.KernelRecovery.SetKernelArgument(0, device.BufferNonce); device.KernelRecovery.SetKernelArgument(1, device.BufferR); device.KernelRecovery.SetKernelArgument(2, device.BufferI2); } catch (Exception ex) { if (isStopSolving) { return; } throw ex; } while (!isStopSolving) { try { while (solutions.TryDequeue(out var solution)) { device.CommandQueue.EnqueueWriteBuffer(device.BufferNonce, solution.Job.NonceHash, 32); device.CommandQueue.EnqueueFillBuffer(device.BufferI2, 64 * 64 * 4, clearPattern); device.CommandQueue.EnqueueWriteBuffer(device.BufferR, solution.GetLongEdges(), CycleFinder.CUCKOO_42); device.CommandQueue.EnqueueNDRangeKernel(device.KernelRecovery, 1, 2048 * 256, 256, 0); solution.nonces = device.CommandQueue.EnqueueReadBuffer <uint>(device.BufferI2, 42); Task.Factory.StartNew(() => { try { solution.nonces = solution.nonces.OrderBy(n => n).ToArray(); if (solution.CheckDifficulty(out ulong currentDiff, out ulong expectDiff)) { Log(Level.Debug, $"Solved difficulty of >={expectDiff} ({currentDiff})"); solution.Job.OnJobSolved(); Log(solution.Job.Origin.Category == FeeCategory.Miner ? Level.Info : Level.Debug, $"Device #{device.DeviceID} submitting solution..."); solution.Job.Origin.SubmitSolution(new SubmitParams() { Height = solution.Job.Height, Nonce = solution.Job.Nonce, JobID = solution.Job.JobID, POW = solution.nonces }); } else { Log(Level.Debug, $"Low difficulty solution of <{expectDiff} ({currentDiff})"); } } catch (Exception ex) { Log(ex); } }); } while (IsPause) { Task.Delay(500).Wait(); } if (currentJob == null) { Task.Delay(500).Wait(); continue; } else if (tempJob == null || tempJob.JobID != currentJob.JobID || tempJob.Height != currentJob.Height) { nextJob = new Job(currentJob, device.DeviceID).NextNonce(); } tempJob = nextJob; var nextJobTask = Task.Factory.StartNew(() => tempJob.NextNonce(), TaskCreationOptions.LongRunning); if (maxLogLevel == Level.Verbose) { timer.Restart(); } device.CommandQueue.EnqueueWriteBuffer(device.BufferNonce, tempJob.NonceHash, 32); device.CommandQueue.EnqueueFillBuffer(device.BufferI2, 64 * 64 * 4, clearPattern); device.CommandQueue.EnqueueFillBuffer(device.BufferI1, 64 * 64 * 4, clearPattern); device.CommandQueue.EnqueueNDRangeKernel(device.KernelSeedA, 1, 2048 * 128, 128, 0); device.CommandQueue.EnqueueNDRangeKernel(device.KernelSeedB1, 1, 1024 * 128, 128, 0); device.CommandQueue.EnqueueNDRangeKernel(device.KernelSeedB2, 1, 1024 * 128, 128, 0); device.CommandQueue.EnqueueFillBuffer(device.BufferI1, 64 * 64 * 4, clearPattern); device.CommandQueue.EnqueueNDRangeKernel(device.KernelRound1, 1, 4096 * 1024, 1024, 0); device.CommandQueue.EnqueueFillBuffer(device.BufferI2, 64 * 64 * 4, clearPattern); device.CommandQueue.EnqueueNDRangeKernel(device.KernelRoundO, 1, 4096 * 1024, 1024, 0); device.CommandQueue.EnqueueFillBuffer(device.BufferI1, 64 * 64 * 4, clearPattern); device.CommandQueue.EnqueueNDRangeKernel(device.KernelRoundNB, 1, 4096 * 1024, 1024, 0); for (int r = 0; r < TrimRounds; r++) { device.CommandQueue.EnqueueFillBuffer(device.BufferI2, 64 * 64 * 4, clearPattern); device.CommandQueue.EnqueueNDRangeKernel(device.KernelRoundNA, 1, 4096 * 1024, 1024, 0); device.CommandQueue.EnqueueFillBuffer(device.BufferI1, 64 * 64 * 4, clearPattern); device.CommandQueue.EnqueueNDRangeKernel(device.KernelRoundNB, 1, 4096 * 1024, 1024, 0); } device.CommandQueue.EnqueueFillBuffer(device.BufferI2, 64 * 64 * 4, clearPattern); device.CommandQueue.EnqueueNDRangeKernel(device.KernelTail, 1, 4096 * 1024, 1024, 0); device.CommandQueue.EnqueueReadBuffer(device.BufferI2, 1, ref edgeCount); if (maxLogLevel == Level.Verbose) { Log(Level.Verbose, $"Device #{device.DeviceID} Job #{tempJob.JobID}: " + $"Trimmed to {edgeCount[0]} edges in {timer.ElapsedMilliseconds}ms"); } tempJob.EndSolveOn = DateTime.Now; if (edgeCount[0] < maxCpuHandleEdgeCount) { device.CommandQueue.EnqueueReadBuffer(device.BufferA1, (int)edgeCount[0] * 2, ref edgeBuffer); var handleJob = tempJob; var tempEdgeCount = (int)edgeCount[0]; var tempEdgeBuffer = edgeBuffer.ToArray(); Task.Factory.StartNew(() => { var uintEdgeBuffer = new uint[tempEdgeCount * sizeof(ulong) / sizeof(uint)]; Buffer.BlockCopy(tempEdgeBuffer, 0, uintEdgeBuffer, 0, tempEdgeCount * sizeof(uint) * 2); tempEdgeBuffer = null; var cf = CycleFinder.GetInstance(); cf.SetJob(handleJob); cf.SetEdges(uintEdgeBuffer, tempEdgeCount); try { if (cpuThreadCount++ < Math.Max(3, Environment.ProcessorCount)) { cf.FindSolutions(solutions); } else { Log(Level.Warn, "CPU overloaded!"); } } finally { cpuThreadCount--; CycleFinder.ReturnInstance(cf); } }, TaskCreationOptions.LongRunning); } AddToJobHistory(tempJob); nextJob = nextJobTask.Result; } catch (Exception ex) { Log(ex); FreeDevice(device); IsAnySolverCrashed = true; break; } } Marshal.FreeHGlobal(clearPattern); }
private void StartSolvingByDevice(Device.CUDA device) { if (isStopSolving) { return; } Job nextJob = null, tempJob = null; Solution foundSolution = null; var cpuThreadCount = 0; var edgeCount = new uint[2]; var edgeBuffer = new ulong[maxCpuHandleEdgeCount]; var maxLogLevel = (Level)Math.Max((int)MinimumLogLevel, (int)MinimumFileLogLevel); var timer = (maxLogLevel == Level.Verbose) ? new Stopwatch() : null; device.Context.SetCurrent(); while (!isStopSolving) { try { if (solutions.TryDequeue(out Solution solution)) { foundSolution = solution; device.IndexesB_device.MemsetAsync(0, device.Stream2.Stream); device.MeanRecover.SetConstantVariable <byte>("nonce", foundSolution.Job.NonceHash); device.MeanRecover.SetConstantVariable <ulong>("recovery", foundSolution.GetUlongEdges()); device.MeanRecover.RunAsync(device.Stream2.Stream, device.IndexesB_device.DevicePointer); } while (IsPause) { Task.Delay(500).Wait(); } if (currentJob == null) { Task.Delay(500).Wait(); continue; } else if (tempJob == null || tempJob.JobID != currentJob.JobID || tempJob.Height != currentJob.Height) { nextJob = new Job(currentJob, device.DeviceID).NextNonce(); } tempJob = nextJob; var nextJobTask = Task.Factory.StartNew(() => tempJob.NextNonce(), TaskCreationOptions.LongRunning); if (maxLogLevel == Level.Verbose) { timer.Restart(); } device.IndexesA_device.MemsetAsync(0, device.Stream1.Stream); device.IndexesC_device.MemsetAsync(0, device.Stream2.Stream); device.MeanSeedA.SetConstantVariable <byte>("nonce", tempJob.NonceHash); device.MeanSeedA.RunAsync(device.Stream1.Stream, device.BufferMid_device.DevicePointer, device.IndexesA_device.DevicePointer); if (foundSolution != null) { device.Stream2.Synchronize(); device.IndexesB_device.CopyToHost(foundSolution.nonces, 0, 0, CycleFinder.CUCKOO_42 * sizeof(uint)); var recoverSolution = foundSolution; foundSolution = null; Task.Factory.StartNew(() => { try { recoverSolution.nonces = recoverSolution.nonces.OrderBy(n => n).ToArray(); if (recoverSolution.CheckDifficulty(out ulong currentDiff, out ulong expectDiff)) { Log(Level.Debug, $"Solved difficulty of >={expectDiff} ({currentDiff})"); recoverSolution.Job.OnJobSolved(); Log(recoverSolution.Job.Origin.Category == FeeCategory.Miner ? Level.Info : Level.Debug, $"Device #{device.DeviceID} submitting solution..."); recoverSolution.Job.Origin.SubmitSolution(new SubmitParams() { Height = recoverSolution.Job.Height, Nonce = recoverSolution.Job.Nonce, JobID = recoverSolution.Job.JobID, POW = recoverSolution.nonces }); } else { Log(Level.Debug, $"Low difficulty solution of <{expectDiff} ({currentDiff})"); } } catch (Exception ex) { Log(ex); } }); } device.IndexesB_device.MemsetAsync(0, device.Stream1.Stream); device.Stream2.Synchronize(); device.Stream1.Synchronize(); for (var i = 0; i < 4; i++) { device.MeanSeedB_4.RunAsync(((i % 2) == 0) ? device.Stream1.Stream : device.Stream2.Stream, device.BufferMid_device.DevicePointer, device.Buffer_device.DevicePointer + (Device.CUDA.BUFFER_SIZE_A * 8 / 4 * i), device.IndexesA_device.DevicePointer, device.IndexesB_device.DevicePointer, i * 16); } device.Stream1.Synchronize(); device.Stream2.Synchronize(); device.MeanRound_2.RunAsync(device.Stream1.Stream, device.Buffer_device.DevicePointer + ((Device.CUDA.BUFFER_SIZE_A * 8) / 4) * 2, device.BufferB_device.DevicePointer, device.IndexesB_device.DevicePointer + (2048 * 4), device.IndexesC_device.DevicePointer + (4096 * 4), Device.CUDA.DUCK_EDGES_A, Device.CUDA.DUCK_EDGES_B / 2); device.MeanRound_2.RunAsync(device.Stream2.Stream, device.Buffer_device.DevicePointer, device.BufferB_device.DevicePointer - (Device.CUDA.BUFFER_SIZE_B * 8), device.IndexesB_device.DevicePointer, device.IndexesC_device.DevicePointer, Device.CUDA.DUCK_EDGES_A, Device.CUDA.DUCK_EDGES_B / 2); device.Stream1.Synchronize(); device.Stream2.Synchronize(); device.IndexesA_device.MemsetAsync(0, device.Stream2.Stream); device.IndexesB_device.MemsetAsync(0, device.Stream2.Stream); device.MeanRoundJoin.RunAsync(device.Stream1.Stream, device.BufferB_device.DevicePointer - (Device.CUDA.BUFFER_SIZE_B * 8), device.BufferB_device.DevicePointer, device.Buffer_device.DevicePointer, device.IndexesC_device.DevicePointer, device.IndexesX_device.DevicePointer, Device.CUDA.DUCK_EDGES_B / 2, Device.CUDA.DUCK_EDGES_B / 2); device.MeanRound.RunAsync(device.Stream1.Stream, device.Buffer_device.DevicePointer, device.BufferB_device.DevicePointer, device.IndexesX_device.DevicePointer, device.IndexesY_device.DevicePointer, Device.CUDA.DUCK_EDGES_B / 2, Device.CUDA.DUCK_EDGES_B / 2); device.MeanRound.RunAsync(device.Stream1.Stream, device.BufferB_device.DevicePointer, device.Buffer_device.DevicePointer, device.IndexesY_device.DevicePointer, device.IndexesZ_device.DevicePointer, Device.CUDA.DUCK_EDGES_B / 2, Device.CUDA.DUCK_EDGES_B / 2); device.Stream2.Synchronize(); device.MeanRound.RunAsync(device.Stream1.Stream, device.Buffer_device.DevicePointer, device.BufferB_device.DevicePointer, device.IndexesZ_device.DevicePointer, device.Indexes_device[0, 0].DevicePointer, Device.CUDA.DUCK_EDGES_B / 2, Device.CUDA.DUCK_EDGES_B / 4); device.Stream1.Synchronize(); device.IndexesX_device.MemsetAsync(0, device.Stream2.Stream); device.IndexesY_device.MemsetAsync(0, device.Stream2.Stream); device.IndexesZ_device.MemsetAsync(0, device.Stream2.Stream); for (var i = 0; i < TrimRounds; i++) { device.MeanRound.RunAsync(device.Stream1.Stream, device.BufferB_device.DevicePointer, device.Buffer_device.DevicePointer, device.Indexes_device[i, 0].DevicePointer, device.Indexes_device[i, 1].DevicePointer, Device.CUDA.DUCK_EDGES_B / 4, Device.CUDA.DUCK_EDGES_B / 4); device.MeanRound.RunAsync(device.Stream1.Stream, device.Buffer_device.DevicePointer, device.BufferB_device.DevicePointer, device.Indexes_device[i, 1].DevicePointer, device.Indexes_device[i + 1, 0].DevicePointer, Device.CUDA.DUCK_EDGES_B / 4, Device.CUDA.DUCK_EDGES_B / 4); } device.MeanTail.RunAsync(device.Stream1.Stream, device.BufferB_device.DevicePointer, device.Buffer_device.DevicePointer, device.Indexes_device[TrimRounds, 0].DevicePointer, device.Indexes_device[TrimRounds, 1].DevicePointer); device.Stream1.Synchronize(); device.Indexes_device[TrimRounds, 1].CopyToHost(edgeCount, 0, 0, 8); foreach (var index in device.Indexes_device) { index.MemsetAsync(0, device.Stream2.Stream); } if (maxLogLevel == Level.Verbose) { Log(Level.Verbose, $"Device #{device.DeviceID} Job #{tempJob.JobID}: " + $"Trimmed to {edgeCount[0]} edges in {timer.ElapsedMilliseconds}ms"); } tempJob.EndSolveOn = DateTime.Now; if (edgeCount[0] < maxCpuHandleEdgeCount) { device.Buffer_device.CopyToHost(edgeBuffer, 0, 0, edgeCount[0] * 8); var handleJob = tempJob; var tempEdgeCount = (int)edgeCount[0]; var tempEdgeBuffer = edgeBuffer.ToArray(); Task.Factory.StartNew(() => { var uintEdgeBuffer = new uint[tempEdgeCount * sizeof(ulong) / sizeof(uint)]; Buffer.BlockCopy(tempEdgeBuffer, 0, uintEdgeBuffer, 0, tempEdgeCount * sizeof(ulong)); tempEdgeBuffer = null; var cf = CycleFinder.GetInstance(); cf.SetJob(handleJob); cf.SetEdges(uintEdgeBuffer, tempEdgeCount); try { if (cpuThreadCount++ < Math.Max(3, Environment.ProcessorCount)) { cf.FindSolutions(solutions); } else { Log(Level.Warn, "CPU overloaded!"); } } finally { cpuThreadCount--; CycleFinder.ReturnInstance(cf); } }, TaskCreationOptions.LongRunning); } AddToJobHistory(tempJob); nextJob = nextJobTask.Result; } catch (Exception ex) { Log(ex); FreeDevice(device); IsAnySolverCrashed = true; break; } } }