예제 #1
0
        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; }
                }
        }
예제 #2
0
        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);
        }
예제 #3
0
        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;
        }
예제 #4
0
        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());
            }
        }