private void FreeDevice(Device.AMD device) { lock (device) if (device.IsInitialized) { try { device.BufferA1?.Dispose(); device.BufferA2?.Dispose(); device.BufferB?.Dispose(); device.BufferI1?.Dispose(); device.BufferI2?.Dispose(); device.BufferNonce?.Dispose(); device.BufferR?.Dispose(); device.KernelSeedA?.Dispose(); device.KernelSeedB1?.Dispose(); device.KernelSeedB2?.Dispose(); device.KernelRound1?.Dispose(); device.KernelRoundO?.Dispose(); device.KernelRoundNA?.Dispose(); device.KernelRoundNB?.Dispose(); device.KernelTail?.Dispose(); device.KernelRecovery?.Dispose(); device.CommandQueue?.Dispose(); device.Program?.Dispose(); device.Context?.Dispose(); } catch (Exception ex) { Log(ex); Log(Level.Error, $"Failed to free buffers at device ID [{device.DeviceID}]"); } finally { device.IsInitialized = false; } } }
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 InitializeDevice(Device.AMD device) { if (!device.Allow) { return; } Log(Level.Debug, $"Initializing device ID [{device.DeviceID}]"); try { device.Context = Context.CreateContext(device.Info); device.Program = device.Context.CreateAndBuildProgramFromString(sKernel); device.CommandQueue = CommandQueue.CreateCommandQueue(device.Context, device.Info); } catch (Exception ex) { Log(ex); Log(Level.Error, $"Failed loading kernel to device ID [{device.DeviceID}]"); return; } try { device.KernelSeedA = device.Program.CreateKernel("FluffySeed2A"); device.KernelSeedB1 = device.Program.CreateKernel("FluffySeed2B"); device.KernelSeedB2 = device.Program.CreateKernel("FluffySeed2B"); device.KernelRound1 = device.Program.CreateKernel("FluffyRound1"); device.KernelRoundO = device.Program.CreateKernel("FluffyRoundNO1"); device.KernelRoundNA = device.Program.CreateKernel("FluffyRoundNON"); device.KernelRoundNB = device.Program.CreateKernel("FluffyRoundNON"); device.KernelTail = device.Program.CreateKernel("FluffyTailO"); device.KernelRecovery = device.Program.CreateKernel("FluffyRecovery"); } catch (Exception ex) { Log(ex); Log(Level.Error, $"Failed loading kernel to device ID [{device.DeviceID}]"); return; } var availableMemory = Math.Round(device.AvailableMemory / Math.Pow(2, 30), 1); try { Log(Level.Debug, $"Allocating video memory on device ID [{device.DeviceID}]"); Log(Level.Info, $"Available video memory on device ID [{device.DeviceID}]: {availableMemory}GB"); device.BufferA1 = device.Context.CreateBuffer <uint>(MemoryFlag.ReadWrite, Device.AMD.BUFFER_SIZE_A1); device.BufferA2 = device.Context.CreateBuffer <uint>(MemoryFlag.ReadWrite, Device.AMD.BUFFER_SIZE_A2); device.BufferB = device.Context.CreateBuffer <uint>(MemoryFlag.ReadWrite, Device.AMD.BUFFER_SIZE_B); device.BufferI1 = device.Context.CreateBuffer <uint>(MemoryFlag.ReadWrite, Device.AMD.INDEX_SIZE); device.BufferI2 = device.Context.CreateBuffer <uint>(MemoryFlag.ReadWrite, Device.AMD.INDEX_SIZE); device.BufferNonce = device.Context.CreateBuffer <byte>(MemoryFlag.ReadOnly, 32); device.BufferR = device.Context.CreateBuffer <uint>(MemoryFlag.ReadOnly, CycleFinder.CUCKOO_42 * 2); } catch (Exception ex) { Log(ex); Log(Level.Error, $"Out of video memory at device ID [{device.DeviceID}], required >{Device.AMD.RequiredGPUMemoryGB()}GB"); return; } device.IsInitialized = true; }
public static AMD[] GetDevices() { try { var platform = Platform.GetPlatforms().FirstOrDefault(p => p.Name.IndexOf("AMD") > -1); var devices = platform.GetDevices(DeviceType.Gpu).Where(d => d.IsAvailable).ToArray(); var deviceList = new List <AMD>(devices.Length); Log(Level.Info, $"{devices.Length} devices found"); for (var id = 0; id < devices.Length; id++) { var newDevice = new AMD() { Type = PlatformType.AMD_APP, Info = devices[id], DeviceID = id, Name = devices[id].Name, // AMD: codename PciBusID = GetDevicePciBusID(devices[id], id) }; deviceList.Add(newDevice); newDevice.Name = GetDeviceName(devices[id], id); // AMD: actual model name newDevice.AvailableMemory = GetAvailableMemory(devices[id], id); newDevice.Allow = ((newDevice.AvailableMemory / Math.Pow(2, 30) * 10) / 10 > RequiredGPUMemoryGB()); if (deviceList.Last().AvailableMemory <= 0) { Console.WriteLine($"Unknown memory count from device #{id} of PCI Bus #{deviceList.Last().PciBusID}" + $" ({deviceList.Last().Name})"); bool?useDevice = null; while (useDevice == null) { Console.WriteLine("Do you want to use it? [Y/N]"); switch (Console.ReadKey().KeyChar) { case 'Y': case 'y': useDevice = true; break; case 'N': case 'n': useDevice = false; break; } Console.WriteLine(); } deviceList.Last().Allow = useDevice.Value; } } Log(Level.Info, $"{deviceList.Count(d => d.Allow)} devices with video memory of >{RequiredGPUMemoryGB()}GB"); return(deviceList.ToArray()); } catch (Exception ex) { Logger.Log(ex); Log(Level.Error, "Failed to get AMD devices"); return(Enumerable.Empty <AMD>().ToArray()); } }