Exemple #1
0
 public OpenCLDummyLbryMiner(OpenCLDevice aGatelessGateDevice)
     : base(aGatelessGateDevice, "Lbry")
 {
     mLbryInputBuffer  = new ComputeBuffer <byte>(Context, ComputeMemoryFlags.ReadOnly, 112);
     mLbryOutputBuffer = new ComputeBuffer <UInt32>(Context, ComputeMemoryFlags.ReadWrite, lbryOutputSize);
     mIterations       = (aGatelessGateDevice.GetVendor() == "NVIDIA") ? 8 : 1;
 }
        private void BuildEthashProgram()
        {
            ComputeDevice computeDevice = OpenCLDevice.GetComputeDevice();

            try { mProgramArrayMutex.WaitOne(5000); } catch (Exception) { }

            if (mEthashProgramArray.ContainsKey(new long[] { DeviceIndex, mEthashLocalWorkSizeArray[0] }))
            {
                mEthashProgram      = mEthashProgramArray[new long[] { DeviceIndex, mEthashLocalWorkSizeArray[0] }];
                mEthashDAGKernel    = mEthashDAGKernelArray[new long[] { DeviceIndex, mEthashLocalWorkSizeArray[0] }];
                mEthashSearchKernel = mEthashSearchKernelArray[new long[] { DeviceIndex, mEthashLocalWorkSizeArray[0] }];
            }
            else
            {
                try
                {
                    if (mEthashLocalWorkSizeArray[0] != 192)
                    {
                        throw new Exception("No suitable binary file was found.");
                    }
                    string fileName = @"BinaryKernels\" + computeDevice.Name + "_ethash.bin";
                    byte[] binary   = System.IO.File.ReadAllBytes(fileName);
                    mEthashProgram = new ComputeProgram(Context, new List <byte[]>()
                    {
                        binary
                    }, new List <ComputeDevice>()
                    {
                        computeDevice
                    });
                    MainForm.Logger("Loaded " + fileName + " for Device #" + DeviceIndex + ".");
                }
                catch (Exception)
                {
                    //MainForm.Logger("ex.message: " + ex.Message);
                    String source = System.IO.File.ReadAllText(@"Kernels\ethash.cl");
                    mEthashProgram = new ComputeProgram(Context, source);
                    MainForm.Logger(@"Loaded Kernels\ethash.cl for Device #" + DeviceIndex + ".");
                }
                String buildOptions = (OpenCLDevice.GetVendor() == "AMD"    ? "-O1 " :
                                       OpenCLDevice.GetVendor() == "NVIDIA" ? "" : // "-cl-nv-opt-level=1 -cl-nv-maxrregcount=256 " :
                                       "")
                                      + " -IKernels -DWORKSIZE=" + mEthashLocalWorkSizeArray[0];
                try
                {
                    mEthashProgram.Build(OpenCLDevice.DeviceList, buildOptions, null, IntPtr.Zero);
                }
                catch (Exception)
                {
                    MainForm.Logger(mEthashProgram.GetBuildLog(computeDevice));
                    throw;
                }
                MainForm.Logger("Built Ethash program for Device #" + DeviceIndex + ".");
                MainForm.Logger("Build options: " + buildOptions);
                mEthashProgramArray[new long[] { DeviceIndex, mEthashLocalWorkSizeArray[0] }]      = mEthashProgram;
                mEthashDAGKernelArray[new long[] { DeviceIndex, mEthashLocalWorkSizeArray[0] }]    = mEthashDAGKernel = mEthashProgram.CreateKernel("GenerateDAG");
                mEthashSearchKernelArray[new long[] { DeviceIndex, mEthashLocalWorkSizeArray[0] }] = mEthashSearchKernel = mEthashProgram.CreateKernel("search");
            }

            try { mProgramArrayMutex.ReleaseMutex(); } catch (Exception) { }
        }
        public void BuildNeoScryptProgram()
        {
            ComputeDevice computeDevice = OpenCLDevice.GetComputeDevice();

            try { mProgramArrayMutex.WaitOne(5000); } catch (Exception) { }

            if (mNeoScryptProgramArray.ContainsKey(new ProgramArrayIndex(DeviceIndex, mNeoScryptLocalWorkSizeArray[0])))
            {
                mNeoScryptProgram      = mNeoScryptProgramArray[new ProgramArrayIndex(DeviceIndex, mNeoScryptLocalWorkSizeArray[0])];
                mNeoScryptSearchKernel = mNeoScryptSearchKernelArray[new ProgramArrayIndex(DeviceIndex, mNeoScryptLocalWorkSizeArray[0])];
            }
            else
            {
                String source = System.IO.File.ReadAllText(@"Kernels\neoscrypt.cl");
                mNeoScryptProgram = new ComputeProgram(Context, source);
                MainForm.Logger(@"Loaded Kernels\neoscrypt.cl for Device #" + DeviceIndex + ".");
                String buildOptions = (OpenCLDevice.GetVendor() == "AMD" ? "-O5 -legacy" : // "-legacy" :
                                       OpenCLDevice.GetVendor() == "NVIDIA" ? "" :         //"-cl-nv-opt-level=1 -cl-nv-maxrregcount=256 " :
                                       "")
                                      + " -IKernels -DWORKSIZE=" + mNeoScryptLocalWorkSizeArray[0];
                try {
                    mNeoScryptProgram.Build(OpenCLDevice.DeviceList, buildOptions, null, IntPtr.Zero);
                } catch (Exception) {
                    MainForm.Logger(mNeoScryptProgram.GetBuildLog(computeDevice));
                    throw;
                }
                MainForm.Logger("Built NeoScrypt program for Device #" + DeviceIndex + ".");
                MainForm.Logger("Build options: " + buildOptions);
                mNeoScryptProgramArray[new ProgramArrayIndex(DeviceIndex, mNeoScryptLocalWorkSizeArray[0])]      = mNeoScryptProgram;
                mNeoScryptSearchKernelArray[new ProgramArrayIndex(DeviceIndex, mNeoScryptLocalWorkSizeArray[0])] = mNeoScryptSearchKernel = mNeoScryptProgram.CreateKernel("search");
            }

            try { mProgramArrayMutex.ReleaseMutex(); } catch (Exception) { }
        }
Exemple #4
0
        protected ComputeProgram BuildProgram(string programName, long localWorkSize, string optionsAMD, string optionsNVIDIA, string optionsOthers)
        {
            ComputeProgram program;
            string         defultBinaryFilePath = @"BinaryKernels\" + ComputeDevice.Name + "_" + programName + "_" + localWorkSize + ".bin";
            string         savedBinaryFilePath  = (MainForm.SavedOpenCLBinaryKernelPathBase + @"\") + ComputeDevice.Name + "_" + programName + "_" + localWorkSize + ".bin";
            string         sourceFilePath       = @"Kernels\" + programName + ".cl";
            String         buildOptions         = (OpenCLDevice.GetVendor() == "AMD" ? optionsAMD : OpenCLDevice.GetVendor() == "NVIDIA" ? optionsNVIDIA : optionsOthers) + " -IKernels -DWORKSIZE=" + localWorkSize;

            try {
                if (!MainForm.UseDefaultOpenCLBinariesChecked)
                {
                    throw new Exception();
                }
                byte[] binary = System.IO.File.ReadAllBytes(defultBinaryFilePath);
                program = new ComputeProgram(Context, new List <byte[]>()
                {
                    binary
                }, new List <ComputeDevice>()
                {
                    ComputeDevice
                });
                MainForm.Logger("Loaded " + defultBinaryFilePath + " for Device #" + DeviceIndex + ".");
            } catch (Exception) {
                try {
                    if (!MainForm.ReuseCompiledBinariesChecked)
                    {
                        throw new Exception();
                    }
                    byte[] binary = System.IO.File.ReadAllBytes(savedBinaryFilePath);
                    program = new ComputeProgram(Context, new List <byte[]>()
                    {
                        binary
                    }, new List <ComputeDevice>()
                    {
                        ComputeDevice
                    });
                    MainForm.Logger("Loaded " + savedBinaryFilePath + " for Device #" + DeviceIndex + ".");
                } catch (Exception) {
                    String source = System.IO.File.ReadAllText(sourceFilePath);
                    program = new ComputeProgram(Context, source);
                    MainForm.Logger(@"Loaded " + sourceFilePath + " for Device #" + DeviceIndex + ".");
                }
            }
            try {
                program.Build(OpenCLDevice.DeviceList, buildOptions, null, IntPtr.Zero);
                if (MainForm.ReuseCompiledBinariesChecked)
                {
                    System.IO.File.WriteAllBytes(savedBinaryFilePath, program.Binaries[0]);
                }
            } catch (Exception) {
                MainForm.Logger(program.GetBuildLog(ComputeDevice));
                program.Dispose();
                throw;
            }
            MainForm.Logger("Built " + programName + " program for Device #" + DeviceIndex + ".");
            MainForm.Logger("Build options: " + buildOptions);

            return(program);
        }
Exemple #5
0
        public void BuildLbryProgram()
        {
            ComputeDevice computeDevice = OpenCLDevice.GetComputeDevice();

            try { mProgramArrayMutex.WaitOne(5000); } catch (Exception) { }

            if (mLbryProgramArray.ContainsKey(new ProgramArrayIndex(DeviceIndex, mLbryLocalWorkSizeArray[0])))
            {
                mLbryProgram      = mLbryProgramArray[new ProgramArrayIndex(DeviceIndex, mLbryLocalWorkSizeArray[0])];
                mLbrySearchKernel = mLbrySearchKernelArray[new ProgramArrayIndex(DeviceIndex, mLbryLocalWorkSizeArray[0])];
            }
            else
            {
                try
                {
                    if (mLbryLocalWorkSizeArray[0] != 256)
                    {
                        throw new Exception("No suitable binary file was found.");
                    }
                    string fileName = @"BinaryKernels\" + computeDevice.Name + "_lbry.bin";
                    byte[] binary   = System.IO.File.ReadAllBytes(fileName);
                    mLbryProgram = new ComputeProgram(Context, new List <byte[]>()
                    {
                        binary
                    }, new List <ComputeDevice>()
                    {
                        computeDevice
                    });
                    //MainForm.Logger("Loaded " + fileName + " for Device #" + DeviceIndex + ".");
                }
                catch (Exception)
                {
                    String source = System.IO.File.ReadAllText(@"Kernels\lbry.cl");
                    mLbryProgram = new ComputeProgram(Context, source);
                    //MainForm.Logger(@"Loaded Kernels\lbry.cl for Device #" + DeviceIndex + ".");
                }
                String buildOptions = (OpenCLDevice.GetVendor() == "AMD" ? "-O1 " : //"-O1 " :
                                       OpenCLDevice.GetVendor() == "NVIDIA" ? "" :  //"-cl-nv-opt-level=1 -cl-nv-maxrregcount=256 " :
                                       "")
                                      + " -IKernels -DWORKSIZE=" + mLbryLocalWorkSizeArray[0] + " -DITERATIONS=" + mIterations;
                try
                {
                    mLbryProgram.Build(OpenCLDevice.DeviceList, buildOptions, null, IntPtr.Zero);
                }
                catch (Exception)
                {
                    MainForm.Logger(mLbryProgram.GetBuildLog(computeDevice));
                    throw;
                }
                //MainForm.Logger("Built Lbry program for Device #" + DeviceIndex + ".");
                //MainForm.Logger("Build options: " + buildOptions);
                mLbryProgramArray[new ProgramArrayIndex(DeviceIndex, mLbryLocalWorkSizeArray[0])]      = mLbryProgram;
                mLbrySearchKernelArray[new ProgramArrayIndex(DeviceIndex, mLbryLocalWorkSizeArray[0])] = mLbrySearchKernel = mLbryProgram.CreateKernel("search_combined");
            }

            try { mProgramArrayMutex.ReleaseMutex(); } catch (Exception) { }
        }
Exemple #6
0
 public OpenCLLbryMiner(OpenCLDevice aGatelessGateDevice)
     : base(aGatelessGateDevice, "Lbry")
 {
     try {
         mLbryInputBuffer  = new ComputeBuffer <byte>(Context, ComputeMemoryFlags.ReadOnly, 112);
         mLbryOutputBuffer = new ComputeBuffer <UInt32>(Context, ComputeMemoryFlags.ReadWrite, lbryOutputSize);
     } catch (Exception ex) {
         throw new UnrecoverableException(ex, GatelessGateDevice);
     }
     mIterations = (aGatelessGateDevice.GetVendor() == "NVIDIA") ? 8 : 1;
 }
Exemple #7
0
        private void BuildEthashProgram()
        {
            ComputeDevice computeDevice = OpenCLDevice.GetComputeDevice();

            try { mProgramArrayMutex.WaitOne(5000); } catch (Exception) { }

            if (mEthashProgramArray.ContainsKey(new long[] { DeviceIndex, mEthashLocalWorkSizeArray[0] }))
            {
                mEthashProgram      = mEthashProgramArray[new long[] { DeviceIndex, mEthashLocalWorkSizeArray[0] }];
                mEthashDAGKernel    = mEthashDAGKernelArray[new long[] { DeviceIndex, mEthashLocalWorkSizeArray[0] }];
                mEthashSearchKernel = mEthashSearchKernelArray[new long[] { DeviceIndex, mEthashLocalWorkSizeArray[0] }];
            }
            else
            {
                String source = System.IO.File.ReadAllText(@"Kernels\ethash_lbry.cl");
                mEthashProgram = new ComputeProgram(Context, source);
                MainForm.Logger(@"Loaded Kernels\ethash_lbry.cl for Device #" + DeviceIndex + ".");
                String buildOptions = (OpenCLDevice.GetVendor() == "AMD"    ? "-O1 " :
                                       OpenCLDevice.GetVendor() == "NVIDIA" ? "" : // "-cl-nv-opt-level=1 -cl-nv-maxrregcount=256 " :
                                       "")
                                      + " -IKernels -DWORKSIZE=" + mEthashLocalWorkSizeArray[0];
                try
                {
                    mEthashProgram.Build(OpenCLDevice.DeviceList, buildOptions, null, IntPtr.Zero);
                }
                catch (Exception)
                {
                    MainForm.Logger(mEthashProgram.GetBuildLog(computeDevice));
                    throw;
                }
                MainForm.Logger("Built Ethash program for Device #" + DeviceIndex + ".");
                MainForm.Logger("Build options: " + buildOptions);
                mEthashProgramArray[new long[] { DeviceIndex, mEthashLocalWorkSizeArray[0] }]      = mEthashProgram;
                mEthashDAGKernelArray[new long[] { DeviceIndex, mEthashLocalWorkSizeArray[0] }]    = mEthashDAGKernel = mEthashProgram.CreateKernel("GenerateDAG");
                mEthashSearchKernelArray[new long[] { DeviceIndex, mEthashLocalWorkSizeArray[0] }] = mEthashSearchKernel = mEthashProgram.CreateKernel("search");
            }

            try { mProgramArrayMutex.ReleaseMutex(); } catch (Exception) { }
        }
Exemple #8
0
 public OpenCLDummyLbryMiner(OpenCLDevice aGatelessGateDevice)
     : base(aGatelessGateDevice, "lbry")
 {
     mIterations = (aGatelessGateDevice.GetVendor() == "NVIDIA") ? 8 : 1;
 }
Exemple #9
0
        override unsafe protected void MinerThread()
        {
            Random        r             = new Random();
            ComputeDevice computeDevice = OpenCLDevice.GetComputeDevice();

            MarkAsAlive();

            MainForm.Logger("Miner thread for Device #" + DeviceIndex + " started.");
            MainForm.Logger("NiceHash mode is " + (NiceHashMode ? "on" : "off") + ".");

            ComputeProgram program;

            try { mProgramArrayMutex.WaitOne(5000); } catch (Exception) { }
            if (mProgramArray.ContainsKey(new ProgramArrayIndex(DeviceIndex, localWorkSizeA[0])))
            {
                program       = mProgramArray[new ProgramArrayIndex(DeviceIndex, localWorkSizeA[0])];
                searchKernel0 = mSearchKernel0Array[new ProgramArrayIndex(DeviceIndex, localWorkSizeA[0])];
                searchKernel1 = mSearchKernel1Array[new ProgramArrayIndex(DeviceIndex, localWorkSizeA[0])];
                searchKernel2 = mSearchKernel2Array[new ProgramArrayIndex(DeviceIndex, localWorkSizeA[0])];
                searchKernel3 = mSearchKernel3Array[new ProgramArrayIndex(DeviceIndex, localWorkSizeA[0])];
            }
            else
            {
                try
                {
                    if (localWorkSizeA[0] != 8)
                    {
                        throw new Exception("No suitable binary file was found.");
                    }
                    string fileName = @"BinaryKernels\" + computeDevice.Name + "_cryptonight.bin";
                    byte[] binary   = System.IO.File.ReadAllBytes(fileName);
                    program = new ComputeProgram(Context, new List <byte[]>()
                    {
                        binary
                    }, new List <ComputeDevice>()
                    {
                        computeDevice
                    });
                    MainForm.Logger("Loaded " + fileName + " for Device #" + DeviceIndex + ".");
                }
                catch (Exception)
                {
                    String source = System.IO.File.ReadAllText(@"Kernels\cryptonight.cl");
                    program = new ComputeProgram(Context, source);
                    MainForm.Logger(@"Loaded Kernels\cryptonight.cl for Device #" + DeviceIndex + ".");
                }
                String buildOptions = (OpenCLDevice.GetVendor() == "AMD"    ? "-O5" : //"-O1 " :
                                       OpenCLDevice.GetVendor() == "NVIDIA" ? "" :    //"-cl-nv-opt-level=1 -cl-nv-maxrregcount=256 " :
                                       "")
                                      + " -IKernels -DWORKSIZE=" + localWorkSizeA[0];
                try
                {
                    program.Build(OpenCLDevice.DeviceList, buildOptions, null, IntPtr.Zero);
                }
                catch (Exception)
                {
                    MainForm.Logger(program.GetBuildLog(computeDevice));
                    throw;
                }
                MainForm.Logger("Built CryptoNight program for Device #" + DeviceIndex + ".");
                MainForm.Logger("Build options: " + buildOptions);
                mProgramArray[new ProgramArrayIndex(DeviceIndex, localWorkSizeA[0])]       = program;
                mSearchKernel0Array[new ProgramArrayIndex(DeviceIndex, localWorkSizeA[0])] = searchKernel0 = program.CreateKernel("search");
                mSearchKernel1Array[new ProgramArrayIndex(DeviceIndex, localWorkSizeA[0])] = searchKernel1 = program.CreateKernel("search1");
                mSearchKernel2Array[new ProgramArrayIndex(DeviceIndex, localWorkSizeA[0])] = searchKernel2 = program.CreateKernel("search2");
                mSearchKernel3Array[new ProgramArrayIndex(DeviceIndex, localWorkSizeA[0])] = searchKernel3 = program.CreateKernel("search3");
            }
            try { mProgramArrayMutex.ReleaseMutex(); } catch (Exception) { }

            fixed(long *globalWorkOffsetAPtr = globalWorkOffsetA)
            fixed(long *globalWorkOffsetBPtr = globalWorkOffsetB)
            fixed(long *globalWorkSizeAPtr   = globalWorkSizeA)
            fixed(long *globalWorkSizeBPtr   = globalWorkSizeB)
            fixed(long *localWorkSizeAPtr    = localWorkSizeA)
            fixed(long *localWorkSizeBPtr    = localWorkSizeB)
            fixed(Int32 * terminatePtr       = terminate)
            fixed(byte *inputPtr             = input)
            fixed(UInt32 * outputPtr         = output)
            {
                while (!Stopped)
                {
                    MarkAsAlive();

                    try {
                        searchKernel0.SetMemoryArgument(0, inputBuffer);
                        searchKernel0.SetMemoryArgument(1, scratchpadsBuffer);
                        searchKernel0.SetMemoryArgument(2, statesBuffer);

                        searchKernel1.SetMemoryArgument(0, scratchpadsBuffer);
                        searchKernel1.SetMemoryArgument(1, statesBuffer);
                        searchKernel1.SetMemoryArgument(2, terminateBuffer);

                        searchKernel2.SetMemoryArgument(0, scratchpadsBuffer);
                        searchKernel2.SetMemoryArgument(1, statesBuffer);

                        searchKernel3.SetMemoryArgument(0, statesBuffer);
                        searchKernel3.SetMemoryArgument(1, outputBuffer);

                        // Wait for the first job to arrive.
                        int elapsedTime = 0;
                        while ((mStratum == null || mStratum.GetJob() == null) && elapsedTime < 60000)
                        {
                            Thread.Sleep(100);
                            elapsedTime += 100;
                        }
                        if (mStratum == null || mStratum.GetJob() == null)
                        {
                            throw new TimeoutException("Stratum server failed to send a new job.");
                        }

                        System.Diagnostics.Stopwatch consoleUpdateStopwatch = new System.Diagnostics.Stopwatch();
                        CryptoNightStratum.Work      work;

                        while (!Stopped && (work = mStratum.GetWork()) != null)
                        {
                            MarkAsAlive();

                            var job = work.GetJob();
                            Array.Copy(Utilities.StringToByteArray(job.Blob), input, 76);
                            byte   localExtranonce = (byte)work.LocalExtranonce;
                            byte[] targetByteArray = Utilities.StringToByteArray(job.Target);
                            UInt32 startNonce;
                            if (NiceHashMode)
                            {
                                startNonce = ((UInt32)input[42] << (8 * 3)) | ((UInt32)localExtranonce << (8 * 2)) | (UInt32)(r.Next(0, int.MaxValue) & (0x0000ffffu));
                            }
                            else
                            {
                                startNonce = ((UInt32)localExtranonce << (8 * 3)) | (UInt32)(r.Next(0, int.MaxValue) & (0x00ffffffu));
                            }
                            UInt32 target = ((UInt32)targetByteArray[0] << 0)
                                            | ((UInt32)targetByteArray[1] << 8)
                                            | ((UInt32)targetByteArray[2] << 16)
                                            | ((UInt32)targetByteArray[3] << 24);
                            searchKernel3.SetValueArgument <UInt32>(2, target);

                            Queue.Write <byte>(inputBuffer, true, 0, 76, (IntPtr)inputPtr, null);

                            consoleUpdateStopwatch.Start();

                            while (!Stopped && mStratum.GetJob().Equals(job))
                            {
                                MarkAsAlive();

                                globalWorkOffsetA[0] = globalWorkOffsetB[0] = startNonce;

                                // Get a new local extranonce if necessary.
                                if (NiceHashMode)
                                {
                                    if ((startNonce & 0xffff) + (UInt32)globalWorkSizeA[0] >= 0x10000)
                                    {
                                        break;
                                    }
                                }
                                else
                                {
                                    if ((startNonce & 0xffffff) + (UInt32)globalWorkSizeA[0] >= 0x1000000)
                                    {
                                        break;
                                    }
                                }

                                System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                                sw.Start();
                                output[255] = 0; // output[255] is used as an atomic counter.
                                Queue.Write <UInt32>(outputBuffer, true, 0, outputSize, (IntPtr)outputPtr, null);
                                terminate[0] = 0;
                                Queue.Write <Int32>(terminateBuffer, true, 0, 1, (IntPtr)terminatePtr, null);
                                Queue.Execute(searchKernel0, globalWorkOffsetA, globalWorkSizeA, localWorkSizeA, null);
                                Queue.Finish();
                                if (Stopped)
                                {
                                    break;
                                }
                                Queue.Execute(searchKernel1, globalWorkOffsetB, globalWorkSizeB, localWorkSizeB, null);
                                Queue.Finish();
                                if (Stopped)
                                {
                                    break;
                                }
                                Queue.Execute(searchKernel2, globalWorkOffsetA, globalWorkSizeA, localWorkSizeA, null);
                                Queue.Finish();
                                if (Stopped)
                                {
                                    break;
                                }
                                Queue.Execute(searchKernel3, globalWorkOffsetB, globalWorkSizeB, localWorkSizeB, null);
                                Queue.Finish(); // Run the above statement before leaving the current local scope.
                                if (Stopped)
                                {
                                    break;
                                }

                                Queue.Read <UInt32>(outputBuffer, true, 0, outputSize, (IntPtr)outputPtr, null);
                                if (mStratum.GetJob().Equals(job))
                                {
                                    for (int i = 0; i < output[255]; ++i)
                                    {
                                        String result = "";
                                        for (int j = 0; j < 8; ++j)
                                        {
                                            UInt32 word = output[256 + i * 8 + j];
                                            result += String.Format("{0:x2}{1:x2}{2:x2}{3:x2}", ((word >> 0) & 0xff), ((word >> 8) & 0xff), ((word >> 16) & 0xff), ((word >> 24) & 0xff));
                                        }
                                        mStratum.Submit(GatelessGateDevice, job, output[i], result);
                                    }
                                }
                                startNonce += (UInt32)globalWorkSizeA[0];

                                sw.Stop();
                                Speed = ((double)globalWorkSizeA[0]) / sw.Elapsed.TotalSeconds;
                                if (consoleUpdateStopwatch.ElapsedMilliseconds >= 10 * 1000)
                                {
                                    MainForm.Logger("Device #" + DeviceIndex + " (CryptoNight): " + String.Format("{0:N2} h/s", Speed));
                                    consoleUpdateStopwatch.Restart();
                                }
                            }
                        }
                    } catch (Exception ex) {
                        MainForm.Logger("Exception in miner thread: " + ex.Message + ex.StackTrace);
                        if (UnrecoverableException.IsUnrecoverableException(ex))
                        {
                            this.UnrecoverableException = new UnrecoverableException(ex, GatelessGateDevice);
                            Stop();
                        }
                    }

                    Speed = 0;

                    if (!Stopped)
                    {
                        MainForm.Logger("Restarting miner thread...");
                        System.Threading.Thread.Sleep(5000);
                    }
                }
            }

            MarkAsDone();
        }