override unsafe protected void MinerThread() { ComputeProgram program = null; ComputeBuffer <byte> statesBuffer = null; ComputeBuffer <byte> scratchpadsBuffer = null; try { Random r = new Random(); var openCLName = OpenCLDevice.GetComputeDevice().Name; var GCN1 = openCLName == "Capeverde" || openCLName == "Hainan" || openCLName == "Oland" || openCLName == "Pitcairn" || openCLName == "Tahiti"; MarkAsAlive(); MainForm.Logger("Miner thread for Device #" + DeviceIndex + " started."); MainForm.Logger("NiceHash mode is " + (NiceHashMode ? "on" : "off") + "."); program = BuildProgram("cryptonight", localWorkSizeA[0], "-O5" + (GCN1 ? " -legacy" : ""), "", ""); statesBuffer = OpenCLDevice.RequestComputeByteBuffer(ComputeMemoryFlags.ReadWrite, 200 * globalWorkSizeA[0]); scratchpadsBuffer = OpenCLDevice.RequestComputeByteBuffer(ComputeMemoryFlags.ReadWrite, ((long)1 << 21) * globalWorkSizeA[0]); using (var searchKernel0 = program.CreateKernel("search")) using (var searchKernel1 = program.CreateKernel("search1")) using (var searchKernel2 = program.CreateKernel("search2")) using (var searchKernel3 = program.CreateKernel("search3")) using (var inputBuffer = new ComputeBuffer <byte>(Context, ComputeMemoryFlags.ReadOnly, 76)) using (var outputBuffer = new ComputeBuffer <UInt32>(Context, ComputeMemoryFlags.ReadWrite, outputSize)) using (var terminateBuffer = new ComputeBuffer <Int32>(Context, ComputeMemoryFlags.ReadWrite, 1)) fixed(Int32 *terminatePtr = terminate) fixed(byte *inputPtr = input) fixed(UInt32 * outputPtr = output) while (!Stopped) { MarkAsAlive(); MemoryUsage = 200 * globalWorkSizeA[0] + ((long)1 << 21) * globalWorkSizeA[0] + 76 + outputSize + 1; 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 ((Stratum == null || Stratum.GetJob() == null) && elapsedTime < Parameters.TimeoutForFirstJobInMilliseconds && !Stopped) { Thread.Sleep(100); elapsedTime += 100; } if (Stratum == null || Stratum.GetJob() == null) { throw new TimeoutException("Stratum server failed to send a new job."); } System.Diagnostics.Stopwatch consoleUpdateStopwatch = new System.Diagnostics.Stopwatch(); CryptoNightStratum.Work work; CryptoNightStratum.Job job; while (!Stopped && (work = Stratum.GetWork()) != null && (job = work.GetJob()) != null) { MarkAsAlive(); 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 && Stratum.GetJob() != null && Stratum.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 (Stratum.GetJob() != null && Stratum.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)); } Stratum.Submit(Device, job, output[i], result); } } startNonce += (UInt32)globalWorkSizeA[0]; sw.Stop(); Speed = ((double)globalWorkSizeA[0]) / sw.Elapsed.TotalSeconds; Device.TotalHashesPrimaryAlgorithm += (double)globalWorkSizeA[0]; if (consoleUpdateStopwatch.ElapsedMilliseconds >= 10 * 1000) { MainForm.Logger("Device #" + DeviceIndex + " (CryptoNight): " + String.Format("{0:N2} h/s", Speed)); consoleUpdateStopwatch.Restart(); } } } } catch (Exception ex) { if (statesBuffer != null) { OpenCLDevice.ReleaseComputeByteBuffer(statesBuffer); statesBuffer = null; } if (scratchpadsBuffer != null) { OpenCLDevice.ReleaseComputeByteBuffer(scratchpadsBuffer); scratchpadsBuffer = null; } MainForm.Logger("Exception in miner thread: " + ex.Message + ex.StackTrace); if (UnrecoverableException.IsUnrecoverableException(ex)) { this.UnrecoverableException = new UnrecoverableException(ex, Device); Stop(); } } Speed = 0; if (!Stopped) { MainForm.Logger("Restarting miner thread..."); System.Threading.Thread.Sleep(Parameters.WaitTimeForRestartingMinerThreadInMilliseconds); } } } catch (UnrecoverableException ex) { this.UnrecoverableException = ex; } catch (Exception ex) { this.UnrecoverableException = new UnrecoverableException(ex, Device); } finally { MarkAsDone(); MemoryUsage = 0; if (program != null) { program.Dispose(); program = null; } if (statesBuffer != null) { OpenCLDevice.ReleaseComputeByteBuffer(statesBuffer); statesBuffer = null; } if (scratchpadsBuffer != null) { OpenCLDevice.ReleaseComputeByteBuffer(scratchpadsBuffer); scratchpadsBuffer = null; } } }
override unsafe protected void MinerThread() { ComputeProgram program = null; ComputeBuffer <byte> neoScryptGlobalCacheBuffer = null; try { Random r = new Random(); MarkAsAlive(); MainForm.Logger("Miner thread for Device #" + DeviceIndex + " started."); program = BuildProgram("neoscrypt", mNeoScryptLocalWorkSizeArray[0], "-O5 -legacy", "", ""); neoScryptGlobalCacheBuffer = OpenCLDevice.RequestComputeByteBuffer(ComputeMemoryFlags.ReadWrite, (mNeoScryptGlobalWorkSizeArray[0] * 32768)); MemoryUsage = sNeoScryptInputSize + sNeoScryptOutputSize + neoScryptGlobalCacheBuffer.Size; using (var neoScryptSearchKernel = program.CreateKernel("search")) using (var neoScryptInputBuffer = new ComputeBuffer <byte>(Context, ComputeMemoryFlags.ReadOnly, sNeoScryptInputSize)) using (var neoScryptOutputBuffer = new ComputeBuffer <UInt32>(Context, ComputeMemoryFlags.ReadWrite, sNeoScryptOutputSize)) fixed(long *neoscryptGlobalWorkOffsetArrayPtr = mNeoScryptGlobalWorkOffsetArray) fixed(long *neoscryptGlobalWorkSizeArrayPtr = mNeoScryptGlobalWorkSizeArray) fixed(long *neoscryptLocalWorkSizeArrayPtr = mNeoScryptLocalWorkSizeArray) fixed(byte *neoscryptInputPtr = mNeoScryptInput) fixed(UInt32 * neoscryptOutputPtr = mNeoScryptOutput) while (!Stopped) { MarkAsAlive(); try { neoScryptSearchKernel.SetMemoryArgument(0, neoScryptInputBuffer); neoScryptSearchKernel.SetMemoryArgument(1, neoScryptOutputBuffer); neoScryptSearchKernel.SetMemoryArgument(2, neoScryptGlobalCacheBuffer); // Wait for the first NeoScryptJob to arrive. int elapsedTime = 0; while ((Stratum == null || Stratum.GetJob() == null) && elapsedTime < Parameters.TimeoutForFirstJobInMilliseconds && !Stopped) { Thread.Sleep(100); elapsedTime += 100; } if (Stratum == null || Stratum.GetJob() == null) { throw new TimeoutException("Stratum server failed to send a new job."); } System.Diagnostics.Stopwatch consoleUpdateStopwatch = new System.Diagnostics.Stopwatch(); NeoScryptStratum.Work neoscryptWork; NeoScryptStratum.Job neoscryptJob; while (!Stopped && (neoscryptWork = Stratum.GetWork()) != null && (neoscryptJob = neoscryptWork.Job) != null) { MarkAsAlive(); Array.Copy(neoscryptWork.Blob, mNeoScryptInput, sNeoScryptInputSize); UInt32 neoscryptStartNonce = (UInt32)(r.Next(0, int.MaxValue)); Queue.Write <byte>(neoScryptInputBuffer, true, 0, sNeoScryptInputSize, (IntPtr)neoscryptInputPtr, null); consoleUpdateStopwatch.Start(); while (!Stopped && Stratum.GetJob() != null && Stratum.GetJob().Equals(neoscryptJob)) { System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); MarkAsAlive(); UInt32 NeoScryptTarget = (UInt32)((double)0xffff0000U / (Stratum.Difficulty * 65536)); neoScryptSearchKernel.SetValueArgument <UInt32>(3, NeoScryptTarget); mNeoScryptGlobalWorkOffsetArray[0] = neoscryptStartNonce; // Get a new local extranonce if necessary. if (0xffffffffu - neoscryptStartNonce < (UInt32)mNeoScryptGlobalWorkSizeArray[0]) { break; } mNeoScryptOutput[255] = 0; // mNeoScryptOutput[255] is used as an atomic counter. Queue.Write <UInt32>(neoScryptOutputBuffer, true, 0, sNeoScryptOutputSize, (IntPtr)neoscryptOutputPtr, null); Queue.Execute(neoScryptSearchKernel, mNeoScryptGlobalWorkOffsetArray, mNeoScryptGlobalWorkSizeArray, mNeoScryptLocalWorkSizeArray, null); Queue.Read <UInt32>(neoScryptOutputBuffer, true, 0, sNeoScryptOutputSize, (IntPtr)neoscryptOutputPtr, null); if (Stratum.GetJob() != null && Stratum.GetJob().Equals(neoscryptJob)) { for (int i = 0; i < mNeoScryptOutput[255]; ++i) { Stratum.Submit(Device, neoscryptWork, mNeoScryptOutput[i]); } } neoscryptStartNonce += (UInt32)mNeoScryptGlobalWorkSizeArray[0]; sw.Stop(); Speed = ((double)mNeoScryptGlobalWorkSizeArray[0]) / sw.Elapsed.TotalSeconds; Device.TotalHashesPrimaryAlgorithm += (double)mNeoScryptGlobalWorkSizeArray[0]; if (consoleUpdateStopwatch.ElapsedMilliseconds >= 10 * 1000) { MainForm.Logger("Device #" + DeviceIndex + ": " + String.Format("{0:N2} Kh/s (NeoScrypt)", Speed / 1000)); consoleUpdateStopwatch.Restart(); } } } } catch (Exception ex) { MainForm.Logger("Exception in miner thread: " + ex.Message + ex.StackTrace); if (UnrecoverableException.IsUnrecoverableException(ex)) { this.UnrecoverableException = new UnrecoverableException(ex, Device); Stop(); } } Speed = 0; if (!Stopped) { MainForm.Logger("Restarting miner thread..."); System.Threading.Thread.Sleep(Parameters.WaitTimeForRestartingMinerThreadInMilliseconds); } } } catch (UnrecoverableException ex) { this.UnrecoverableException = ex; } catch (Exception ex) { this.UnrecoverableException = new UnrecoverableException(ex, Device); } finally { MarkAsDone(); MemoryUsage = 0; if (program != null) { program.Dispose(); program = null; } if (neoScryptGlobalCacheBuffer != null) { OpenCLDevice.ReleaseComputeByteBuffer(neoScryptGlobalCacheBuffer); neoScryptGlobalCacheBuffer = null; } } }