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() { Random r = new Random(); MarkAsAlive(); MainForm.Logger("Dual Ethash/Lbry miner thread for Device #" + DeviceIndex + " started."); BuildEthashProgram(); fixed(UInt32 *ethashOutputPtr = mEthashOutput) fixed(byte *ethashHeaderhashPtr = mEthashHeaderhash) fixed(byte *lbryInputPtr = mLbryInput) fixed(UInt32 * lbryOutputPtr = mLbryOutput) while (!Stopped) { MarkAsAlive(); try { int ethashEpoch = -1; long ethashDAGSize = 0; ComputeBuffer <byte> ethashDAGBuffer = null; // Wait for the first job to arrive. int elapsedTime = 0; while ((mEthashStratum == null || mEthashStratum.GetJob() == null || mLbryStratum == null || mLbryStratum.GetJob() == null) && elapsedTime < Parameters.TimeoutForFirstJobInMilliseconds && !Stopped) { Thread.Sleep(100); elapsedTime += 100; } if (mEthashStratum == null || mEthashStratum.GetJob() == null || mLbryStratum == null || mLbryStratum.GetJob() == null) { MainForm.Logger("Stratum server failed to send a new job."); return; } System.Diagnostics.Stopwatch consoleUpdateStopwatch = new System.Diagnostics.Stopwatch(); EthashStratum.Work ethashWork; LbryStratum.Work lbryWork; mEthashSearchKernel.SetMemoryArgument(7, mLbryInputBuffer); mEthashSearchKernel.SetMemoryArgument(8, mLbryOutputBuffer); while (!Stopped && (ethashWork = mEthashStratum.GetWork()) != null && (lbryWork = mLbryStratum.GetWork()) != null) { MarkAsAlive(); String ethashPoolExtranonce = mEthashStratum.PoolExtranonce; byte[] ethashExtranonceByteArray = Utilities.StringToByteArray(ethashPoolExtranonce); byte ethashLocalExtranonce = (byte)ethashWork.LocalExtranonce; UInt64 ethashStartNonce = (UInt64)ethashLocalExtranonce << (8 * (7 - ethashExtranonceByteArray.Length)); for (int i = 0; i < ethashExtranonceByteArray.Length; ++i) { ethashStartNonce |= (UInt64)ethashExtranonceByteArray[i] << (8 * (7 - i)); } ethashStartNonce += (ulong)r.Next(0, int.MaxValue) & (0xfffffffffffffffful >> (ethashExtranonceByteArray.Length * 8 + 8)); String ethashJobID = ethashWork.GetJob().ID; String ethashSeedhash = ethashWork.GetJob().Seedhash; double ethashDifficulty = mEthashStratum.Difficulty; Buffer.BlockCopy(Utilities.StringToByteArray(ethashWork.GetJob().Headerhash), 0, mEthashHeaderhash, 0, 32); Queue.Write <byte>(mEthashHeaderBuffer, true, 0, 32, (IntPtr)ethashHeaderhashPtr, null); var lbryJob = lbryWork.Job; Array.Copy(lbryWork.Blob, mLbryInput, 112); UInt32 lbryStartNonce = (UInt32)(r.Next(0, int.MaxValue)); UInt64 lbryTarget = (UInt64)((double)0xffff0000UL / (mLbryStratum.Difficulty / 256)); mEthashSearchKernel.SetValueArgument <UInt64>(10, lbryTarget); Queue.Write <byte>(mLbryInputBuffer, true, 0, 112, (IntPtr)lbryInputPtr, null); if (ethashEpoch != ethashWork.GetJob().Epoch) { if (ethashDAGBuffer != null) { ethashDAGBuffer.Dispose(); ethashDAGBuffer = null; } ethashEpoch = ethashWork.GetJob().Epoch; DAGCache cache = new DAGCache(ethashEpoch, ethashWork.GetJob().Seedhash); ethashDAGSize = Utilities.GetDAGSize(ethashEpoch); System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); mEthashGlobalWorkSizeArray[0] = ethashDAGSize / 64; mEthashGlobalWorkSizeArray[0] /= 8; if (mEthashGlobalWorkSizeArray[0] % mEthashLocalWorkSizeArray[0] > 0) { mEthashGlobalWorkSizeArray[0] += mEthashLocalWorkSizeArray[0] - mEthashGlobalWorkSizeArray[0] % mEthashLocalWorkSizeArray[0]; } ComputeBuffer <byte> DAGCacheBuffer = new ComputeBuffer <byte>(Context, ComputeMemoryFlags.ReadOnly, cache.GetData().Length); fixed(byte *p = cache.GetData()) Queue.Write <byte>(DAGCacheBuffer, true, 0, cache.GetData().Length, (IntPtr)p, null); ethashDAGBuffer = new ComputeBuffer <byte>(Context, ComputeMemoryFlags.ReadWrite, mEthashGlobalWorkSizeArray[0] * 8 * 64 /* ethashDAGSize */); // With this, we can remove a conditional statement in the DAG kernel. mEthashDAGKernel.SetValueArgument <UInt32>(0, 0); mEthashDAGKernel.SetMemoryArgument(1, DAGCacheBuffer); mEthashDAGKernel.SetMemoryArgument(2, ethashDAGBuffer); mEthashDAGKernel.SetValueArgument <UInt32>(3, (UInt32)cache.GetData().Length / 64); mEthashDAGKernel.SetValueArgument <UInt32>(4, 0xffffffffu); for (long start = 0; start < ethashDAGSize / 64; start += mEthashGlobalWorkSizeArray[0]) { mEthashGlobalWorkOffsetArray[0] = start; Queue.Execute(mEthashDAGKernel, mEthashGlobalWorkOffsetArray, mEthashGlobalWorkSizeArray, mEthashLocalWorkSizeArray, null); Queue.Finish(); if (Stopped || !mEthashStratum.GetJob().ID.Equals(ethashJobID)) { break; } } DAGCacheBuffer.Dispose(); if (Stopped || !mEthashStratum.GetJob().ID.Equals(ethashJobID)) { break; } sw.Stop(); MainForm.Logger("Generated DAG for Epoch #" + ethashEpoch + " (" + (long)sw.Elapsed.TotalMilliseconds + "ms)."); } consoleUpdateStopwatch.Start(); while (!Stopped && mEthashStratum.GetJob().ID.Equals(ethashJobID) && mEthashStratum.PoolExtranonce.Equals(ethashPoolExtranonce) && mLbryStratum.GetJob().Equals(lbryJob)) { System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); MarkAsAlive(); mEthashGlobalWorkOffsetArray[0] = 0; mEthashSearchKernel.SetValueArgument <UInt32>(9, lbryStartNonce);; // Get a new local extranonce if necessary. if ((ethashStartNonce & (0xfffffffffffffffful >> (ethashExtranonceByteArray.Length * 8 + 8)) + (ulong)mEthashGlobalWorkSizeArray[0] * 3 / 4) >= ((ulong)0x1 << (64 - (ethashExtranonceByteArray.Length * 8 + 8)))) { break; } if (0xffffffffu - lbryStartNonce < (UInt32)mEthashGlobalWorkSizeArray[0] / 4) { break; } UInt64 target = (UInt64)((double)0xffff0000U / ethashDifficulty); mEthashSearchKernel.SetMemoryArgument(0, mEthashOutputBuffer); // g_output mEthashSearchKernel.SetMemoryArgument(1, mEthashHeaderBuffer); // g_header mEthashSearchKernel.SetMemoryArgument(2, ethashDAGBuffer); // _g_dag mEthashSearchKernel.SetValueArgument <UInt32>(3, (UInt32)(ethashDAGSize / 128)); // DAG_SIZE mEthashSearchKernel.SetValueArgument <UInt64>(4, ethashStartNonce); // start_nonce mEthashSearchKernel.SetValueArgument <UInt64>(5, target); // target mEthashSearchKernel.SetValueArgument <UInt32>(6, 0xffffffffu); // isolate mEthashOutput[255] = 0; // mEthashOutput[255] is used as an atomic counter. Queue.Write <UInt32>(mEthashOutputBuffer, true, 0, 256, (IntPtr)ethashOutputPtr, null); mLbryOutput[255] = 0; // mLbryOutput[255] is used as an atomic counter. Queue.Write <UInt32>(mLbryOutputBuffer, true, 0, lbryOutputSize, (IntPtr)lbryOutputPtr, null); Queue.Execute(mEthashSearchKernel, mEthashGlobalWorkOffsetArray, mEthashGlobalWorkSizeArray, mEthashLocalWorkSizeArray, null); Queue.Read <UInt32>(mEthashOutputBuffer, true, 0, 256, (IntPtr)ethashOutputPtr, null); if (mEthashStratum.GetJob().ID.Equals(ethashJobID)) { for (int i = 0; i < mEthashOutput[255]; ++i) { mEthashStratum.Submit(Device, ethashWork.GetJob(), ethashStartNonce + (UInt64)mEthashOutput[i]); } } ethashStartNonce += (UInt64)mEthashGlobalWorkSizeArray[0] * 3 / 4; Queue.Read <UInt32>(mLbryOutputBuffer, true, 0, lbryOutputSize, (IntPtr)lbryOutputPtr, null); if (mLbryStratum.GetJob().Equals(lbryJob)) { for (int i = 0; i < mLbryOutput[255]; ++i) { String result = ""; for (int j = 0; j < 8; ++j) { UInt32 word = mLbryOutput[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)); } mLbryStratum.Submit(Device, lbryWork, mLbryOutput[i], result); } } lbryStartNonce += (UInt32)mEthashGlobalWorkSizeArray[0] / 4; sw.Stop(); Speed = ((double)mEthashGlobalWorkSizeArray[0] * 3 / 4) / sw.Elapsed.TotalSeconds; double speedSecondary = (((double)mEthashGlobalWorkSizeArray[0] / 4) / sw.Elapsed.TotalSeconds); if (consoleUpdateStopwatch.ElapsedMilliseconds >= 10 * 1000) { MainForm.Logger("Device #" + DeviceIndex + " (Ethash): " + String.Format("{0:N2} Mh/s (Ethash), {1:N2} Mh/s (Lbry)", Speed / (1000000), speedSecondary / (1000000))); consoleUpdateStopwatch.Restart(); } } } if (ethashDAGBuffer != null) { ethashDAGBuffer.Dispose(); ethashDAGBuffer = null; } } catch (Exception ex) { MainForm.Logger("Exception in miner thread: " + ex.Message + ex.StackTrace); Speed = 0; if (UnrecoverableException.IsUnrecoverableException(ex)) { this.UnrecoverableException = new UnrecoverableException(ex, Device); Stop(); } else { MainForm.Logger("Restarting miner thread..."); System.Threading.Thread.Sleep(5000); } } } MarkAsDone(); }
override unsafe protected void MinerThread() { Random r = new Random(); UInt32[] ethashOutput = new UInt32[256]; byte[] ethashHeaderhash = new byte[32]; MarkAsAlive(); MainForm.Logger("Miner thread for Device #" + DeviceIndex + " started."); BuildEthashProgram(); fixed(UInt32 *ethashOutputPtr = ethashOutput) fixed(byte *ethashHeaderhashPtr = ethashHeaderhash) fixed(byte *pascalMidstatePtr = mPascalMidstate) fixed(byte *pascalInputPtr = mPascalInput) fixed(UInt32 * pascalOutputPtr = mPascalOutput) while (!Stopped) { MarkAsAlive(); try { int ethashEpoch = -1; long ethashDAGSize = 0; ComputeBuffer <byte> ethashDAGBuffer = null; mEthashSearchKernel.SetMemoryArgument(7 + 0, mPascalInputBuffer); mEthashSearchKernel.SetMemoryArgument(7 + 1, mPascalOutputBuffer); mEthashSearchKernel.SetMemoryArgument(7 + 4, mPascalMidstateBuffer); mEthashSearchKernel.SetValueArgument <UInt32>(7 + 5, mPascalRatio); // Wait for the first job to arrive. int elapsedTime = 0; while ((mEthashStratum == null || mEthashStratum.GetJob() == null || mPascalStratum == null || mPascalStratum.GetJob() == null) && elapsedTime < 60000) { Thread.Sleep(100); elapsedTime += 100; } if (mEthashStratum == null || mEthashStratum.GetJob() == null || mPascalStratum == null || mPascalStratum.GetJob() == null) { MainForm.Logger("Ethash stratum server failed to send a new job."); //throw new TimeoutException("Stratum server failed to send a new job."); return; } System.Diagnostics.Stopwatch consoleUpdateStopwatch = new System.Diagnostics.Stopwatch(); EthashStratum.Work ethashWork; PascalStratum.Work pascalWork; while (!Stopped && (ethashWork = mEthashStratum.GetWork()) != null && (pascalWork = mPascalStratum.GetWork()) != null) { MarkAsAlive(); String ethashPoolExtranonce = mEthashStratum.PoolExtranonce; byte[] ethashExtranonceByteArray = Utilities.StringToByteArray(ethashPoolExtranonce); byte ethashLocalExtranonce = (byte)ethashWork.LocalExtranonce; UInt64 ethashStartNonce = (UInt64)ethashLocalExtranonce << (8 * (7 - ethashExtranonceByteArray.Length)); for (int i = 0; i < ethashExtranonceByteArray.Length; ++i) { ethashStartNonce |= (UInt64)ethashExtranonceByteArray[i] << (8 * (7 - i)); } ethashStartNonce += (ulong)r.Next(0, int.MaxValue) & (0xfffffffffffffffful >> (ethashExtranonceByteArray.Length * 8 + 8)); String ethashJobID = ethashWork.GetJob().ID; String ethashSeedhash = ethashWork.GetJob().Seedhash; double ethashDifficulty = mEthashStratum.Difficulty; Buffer.BlockCopy(Utilities.StringToByteArray(ethashWork.GetJob().Headerhash), 0, ethashHeaderhash, 0, 32); Queue.Write <byte>(mEthashHeaderBuffer, true, 0, 32, (IntPtr)ethashHeaderhashPtr, null); var pascalJob = pascalWork.Job; Array.Copy(pascalWork.Blob, mPascalInput, sPascalInputSize); CalculatePascalMidState(); Queue.Write <byte>(mPascalMidstateBuffer, true, 0, sPascalMidstateSize, (IntPtr)pascalMidstatePtr, null); UInt32 pascalStartNonce = (UInt32)(r.Next(0, int.MaxValue)); UInt64 PascalTarget = (UInt64)((double)0xffff0000UL / mPascalStratum.Difficulty); mEthashSearchKernel.SetValueArgument <UInt64>(7 + 3, PascalTarget); Queue.Write <byte>(mPascalInputBuffer, true, 0, sPascalInputSize, (IntPtr)pascalInputPtr, null); if (ethashEpoch != ethashWork.GetJob().Epoch) { if (ethashDAGBuffer != null) { ethashDAGBuffer.Dispose(); ethashDAGBuffer = null; } ethashEpoch = ethashWork.GetJob().Epoch; DAGCache cache = new DAGCache(ethashEpoch, ethashWork.GetJob().Seedhash); ethashDAGSize = Utilities.GetDAGSize(ethashEpoch); System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); mEthashGlobalWorkSizeArray[0] = ethashDAGSize / 64; mEthashGlobalWorkSizeArray[0] /= 8; if (mEthashGlobalWorkSizeArray[0] % mEthashLocalWorkSizeArray[0] > 0) { mEthashGlobalWorkSizeArray[0] += mEthashLocalWorkSizeArray[0] - mEthashGlobalWorkSizeArray[0] % mEthashLocalWorkSizeArray[0]; } ComputeBuffer <byte> DAGCacheBuffer = new ComputeBuffer <byte>(Context, ComputeMemoryFlags.ReadOnly, cache.GetData().Length); fixed(byte *p = cache.GetData()) Queue.Write <byte>(DAGCacheBuffer, true, 0, cache.GetData().Length, (IntPtr)p, null); ethashDAGBuffer = new ComputeBuffer <byte>(Context, ComputeMemoryFlags.ReadWrite, mEthashGlobalWorkSizeArray[0] * 8 * 64 /* ethashDAGSize */); // With this, we can remove a conditional statement in the DAG kernel. mEthashDAGKernel.SetValueArgument <UInt32>(0, 0); mEthashDAGKernel.SetMemoryArgument(1, DAGCacheBuffer); mEthashDAGKernel.SetMemoryArgument(2, ethashDAGBuffer); mEthashDAGKernel.SetValueArgument <UInt32>(3, (UInt32)cache.GetData().Length / 64); mEthashDAGKernel.SetValueArgument <UInt32>(4, 0xffffffffu); for (long start = 0; start < ethashDAGSize / 64; start += mEthashGlobalWorkSizeArray[0]) { mEthashGlobalWorkOffsetArray[0] = start; Queue.Execute(mEthashDAGKernel, mEthashGlobalWorkOffsetArray, mEthashGlobalWorkSizeArray, mEthashLocalWorkSizeArray, null); Queue.Finish(); if (Stopped || !mEthashStratum.GetJob().ID.Equals(ethashJobID)) { break; } } DAGCacheBuffer.Dispose(); if (Stopped || !mEthashStratum.GetJob().ID.Equals(ethashJobID)) { break; } sw.Stop(); MainForm.Logger("Generated DAG for Epoch #" + ethashEpoch + " (" + (long)sw.Elapsed.TotalMilliseconds + "ms)."); } consoleUpdateStopwatch.Start(); while (!Stopped && mEthashStratum.GetJob().ID.Equals(ethashJobID) && mEthashStratum.PoolExtranonce.Equals(ethashPoolExtranonce) && mPascalStratum.GetJob().Equals(pascalJob)) { System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); MarkAsAlive(); // Get a new local extranonce if necessary. if ((ethashStartNonce & (0xfffffffffffffffful >> (ethashExtranonceByteArray.Length * 8 + 8)) + (ulong)mEthashGlobalWorkSizeArray[0] * 3 / 4) >= ((ulong)0x1 << (64 - (ethashExtranonceByteArray.Length * 8 + 8)))) { break; } if (0xffffffffu - pascalStartNonce < (UInt32)mEthashGlobalWorkSizeArray[0] * mPascalRatio) { break; } UInt64 target = (UInt64)((double)0xffff0000U / ethashDifficulty); mEthashSearchKernel.SetMemoryArgument(0, mEthashOutputBuffer); // g_output mEthashSearchKernel.SetMemoryArgument(1, mEthashHeaderBuffer); // g_header mEthashSearchKernel.SetMemoryArgument(2, ethashDAGBuffer); // _g_dag mEthashSearchKernel.SetValueArgument <UInt32>(3, (UInt32)(ethashDAGSize / 128)); // DAG_SIZE mEthashSearchKernel.SetValueArgument <UInt64>(4, ethashStartNonce); // start_nonce mEthashSearchKernel.SetValueArgument <UInt64>(5, target); // target mEthashSearchKernel.SetValueArgument <UInt32>(6, 0xffffffffu); // isolate mEthashSearchKernel.SetValueArgument <UInt32>(7 + 2, pascalStartNonce); ethashOutput[255] = 0; // ethashOutput[255] is used as an atomic counter. Queue.Write <UInt32>(mEthashOutputBuffer, true, 0, 256, (IntPtr)ethashOutputPtr, null); mEthashGlobalWorkOffsetArray[0] = 0; mPascalOutput[255] = 0; // mPascalOutput[255] is used as an atomic counter. Queue.Write <UInt32>(mPascalOutputBuffer, true, 0, sPascalOutputSize, (IntPtr)pascalOutputPtr, null); Queue.Execute(mEthashSearchKernel, mEthashGlobalWorkOffsetArray, mEthashGlobalWorkSizeArray, mEthashLocalWorkSizeArray, null); Queue.Read <UInt32>(mEthashOutputBuffer, true, 0, 256, (IntPtr)ethashOutputPtr, null); if (mEthashStratum.GetJob().ID.Equals(ethashJobID)) { for (int i = 0; i < ethashOutput[255]; ++i) { mEthashStratum.Submit(GatelessGateDevice, ethashWork.GetJob(), ethashStartNonce + (UInt64)ethashOutput[i]); } } ethashStartNonce += (UInt64)mEthashGlobalWorkSizeArray[0] * 3 / 4; Queue.Read <UInt32>(mPascalOutputBuffer, true, 0, sPascalOutputSize, (IntPtr)pascalOutputPtr, null); if (mPascalStratum.GetJob().Equals(pascalJob)) { for (int i = 0; i < mPascalOutput[255]; ++i) { mPascalStratum.Submit(GatelessGateDevice, pascalWork, mPascalOutput[i]); } } pascalStartNonce += (UInt32)mEthashGlobalWorkSizeArray[0] * mPascalRatio; sw.Stop(); Speed = ((double)mEthashGlobalWorkSizeArray[0]) / sw.Elapsed.TotalSeconds * 0.75; SecondSpeed = ((double)mEthashGlobalWorkSizeArray[0]) / sw.Elapsed.TotalSeconds * mPascalRatio; if (consoleUpdateStopwatch.ElapsedMilliseconds >= 10 * 1000) { MainForm.Logger("Device #" + DeviceIndex + ": " + String.Format("{0:N2} Mh/s (Ethash), ", Speed / (1000000)) + String.Format("{0:N2} Mh/s (Pascal)", SecondSpeed / (1000000))); consoleUpdateStopwatch.Restart(); } } } if (ethashDAGBuffer != null) { ethashDAGBuffer.Dispose(); ethashDAGBuffer = null; } } catch (Exception ex) { MainForm.Logger("Exception in miner thread: " + ex.Message + ex.StackTrace); Speed = 0; if (UnrecoverableException.IsUnrecoverableException(ex)) { this.UnrecoverableException = new UnrecoverableException(ex, GatelessGateDevice); Stop(); } else { MainForm.Logger("Restarting miner thread..."); System.Threading.Thread.Sleep(5000); } } } MarkAsDone(); }
override unsafe protected void MinerThread() { ComputeProgram program = null; try { Random r = new Random(); MarkAsAlive(); MainForm.Logger("Miner thread for Device #" + DeviceIndex + " started."); program = BuildProgram("pascal", mPascalLocalWorkSizeArray[0], "-O1", "", ""); using (var pascalSearchKernel = program.CreateKernel("search")) using (var pascalInputBuffer = new ComputeBuffer <byte>(Context, ComputeMemoryFlags.ReadOnly, sPascalInputSize)) using (var pascalOutputBuffer = new ComputeBuffer <UInt32>(Context, ComputeMemoryFlags.ReadWrite, sPascalOutputSize)) using (var pascalMidstateBuffer = new ComputeBuffer <byte>(Context, ComputeMemoryFlags.ReadOnly, sPascalMidstateSize)) fixed(long *pascalGlobalWorkOffsetArrayPtr = mPascalGlobalWorkOffsetArray) fixed(long *pascalGlobalWorkSizeArrayPtr = mPascalGlobalWorkSizeArray) fixed(long *pascalLocalWorkSizeArrayPtr = mPascalLocalWorkSizeArray) fixed(byte *pascalMidstatePtr = mPascalMidstate) fixed(byte *pascalInputPtr = mPascalInput) fixed(UInt32 * pascalOutputPtr = mPascalOutput) while (!Stopped) { MarkAsAlive(); try { pascalSearchKernel.SetMemoryArgument(0, pascalInputBuffer); pascalSearchKernel.SetMemoryArgument(1, pascalOutputBuffer); pascalSearchKernel.SetMemoryArgument(4, pascalMidstateBuffer); // Wait for the first PascalJob 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 PascalJob."); } System.Diagnostics.Stopwatch consoleUpdateStopwatch = new System.Diagnostics.Stopwatch(); PascalStratum.Work pascalWork; PascalStratum.Job pascalJob; while (!Stopped && (pascalWork = Stratum.GetWork()) != null && (pascalJob = pascalWork.Job) != null) { MarkAsAlive(); Array.Copy(pascalWork.Blob, mPascalInput, sPascalInputSize); CalculatePascalMidState(); Queue.Write <byte>(pascalMidstateBuffer, true, 0, sPascalMidstateSize, (IntPtr)pascalMidstatePtr, null); UInt32 pascalStartNonce = (UInt32)(r.Next(0, int.MaxValue)); UInt64 PascalTarget = (UInt64)((double)0xffff0000UL / Stratum.Difficulty); pascalSearchKernel.SetValueArgument <UInt64>(3, PascalTarget); Queue.Write <byte>(pascalInputBuffer, true, 0, sPascalInputSize, (IntPtr)pascalInputPtr, null); consoleUpdateStopwatch.Start(); while (!Stopped && Stratum.GetJob() != null && Stratum.GetJob().Equals(pascalJob)) { System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); MarkAsAlive(); pascalSearchKernel.SetValueArgument <UInt32>(2, pascalStartNonce); // Get a new local extranonce if necessary. if (0xffffffffu - pascalStartNonce < (UInt32)mPascalGlobalWorkSizeArray[0]) { break; } mPascalOutput[255] = 0; // mPascalOutput[255] is used as an atomic counter. Queue.Write <UInt32>(pascalOutputBuffer, true, 0, sPascalOutputSize, (IntPtr)pascalOutputPtr, null); Queue.Execute(pascalSearchKernel, mPascalGlobalWorkOffsetArray, mPascalGlobalWorkSizeArray, mPascalLocalWorkSizeArray, null); Queue.Read <UInt32>(pascalOutputBuffer, true, 0, sPascalOutputSize, (IntPtr)pascalOutputPtr, null); if (Stratum.GetJob() != null && Stratum.GetJob().Equals(pascalJob)) { for (int i = 0; i < mPascalOutput[255]; ++i) { Stratum.Submit(Device, pascalWork, mPascalOutput[i]); } } pascalStartNonce += (UInt32)mPascalGlobalWorkSizeArray[0]; sw.Stop(); Speed = ((double)mPascalGlobalWorkSizeArray[0]) / sw.Elapsed.TotalSeconds; Device.TotalHashesPrimaryAlgorithm += (double)mPascalGlobalWorkSizeArray[0]; if (consoleUpdateStopwatch.ElapsedMilliseconds >= 10 * 1000) { MainForm.Logger("Device #" + DeviceIndex + ": " + String.Format("{0:N2} Mh/s (Pascal)", Speed / 1000000)); 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); } } MarkAsDone(); program.Dispose(); } catch (UnrecoverableException ex) { if (program != null) { program.Dispose(); } this.UnrecoverableException = ex; } catch (Exception ex) { if (program != null) { program.Dispose(); } this.UnrecoverableException = new UnrecoverableException(ex, Device); } }
override unsafe protected void MinerThread() { ComputeProgram program = null; try { Random r = new Random(); ComputeDevice computeDevice = OpenCLDevice.GetComputeDevice(); UInt32[] ethashOutput = new UInt32[256]; byte[] ethashHeaderhash = new byte[32]; MarkAsAlive(); MainForm.Logger("Miner thread for Device #" + DeviceIndex + " started."); program = BuildProgram("ethash", mEthashLocalWorkSizeArray[0], "-O1", "", ""); MemoryUsage = 256 + 32; using (var searchKernel = program.CreateKernel("search")) using (var DAGKernel = program.CreateKernel("GenerateDAG")) using (var ethashOutputBuffer = new ComputeBuffer <UInt32>(Context, ComputeMemoryFlags.ReadWrite, 256)) using (var ethashHeaderBuffer = new ComputeBuffer <byte>(Context, ComputeMemoryFlags.ReadOnly, 32)) fixed(UInt32 *ethashOutputPtr = ethashOutput) fixed(byte *ethashHeaderhashPtr = ethashHeaderhash) while (!Stopped) { ComputeBuffer <byte> ethashDAGBuffer = null; MarkAsAlive(); try { int ethashEpoch = -1; long ethashDAGSize = 0; // 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) { MainForm.Logger("Ethash stratum server failed to send a new job."); //throw new TimeoutException("Stratum server failed to send a new job."); return; } System.Diagnostics.Stopwatch consoleUpdateStopwatch = new System.Diagnostics.Stopwatch(); EthashStratum.Work ethashWork; EthashStratum.Job ethashJob; while (!Stopped && (ethashWork = Stratum.GetWork()) != null && (ethashJob = ethashWork.GetJob()) != null) { MarkAsAlive(); String ethashPoolExtranonce = Stratum.PoolExtranonce; byte[] ethashExtranonceByteArray = Utilities.StringToByteArray(ethashPoolExtranonce); byte ethashLocalExtranonce = (byte)ethashWork.LocalExtranonce; UInt64 ethashStartNonce = (UInt64)ethashLocalExtranonce << (8 * (7 - ethashExtranonceByteArray.Length)); for (int i = 0; i < ethashExtranonceByteArray.Length; ++i) { ethashStartNonce |= (UInt64)ethashExtranonceByteArray[i] << (8 * (7 - i)); } ethashStartNonce += (ulong)r.Next(0, int.MaxValue) & (0xfffffffffffffffful >> (ethashExtranonceByteArray.Length * 8 + 8)); String ethashJobID = ethashJob.ID; String ethashSeedhash = ethashJob.Seedhash; double ethashDifficulty = Stratum.Difficulty; Buffer.BlockCopy(Utilities.StringToByteArray(ethashWork.GetJob().Headerhash), 0, ethashHeaderhash, 0, 32); Queue.Write <byte>(ethashHeaderBuffer, true, 0, 32, (IntPtr)ethashHeaderhashPtr, null); if (ethashEpoch != ethashWork.GetJob().Epoch) { if (ethashDAGBuffer != null) { MemoryUsage -= ethashDAGBuffer.Size; ethashDAGBuffer.Dispose(); ethashDAGBuffer = null; } ethashEpoch = ethashWork.GetJob().Epoch; DAGCache cache = new DAGCache(ethashEpoch, ethashWork.GetJob().Seedhash); ethashDAGSize = Utilities.GetDAGSize(ethashEpoch); System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); mEthashGlobalWorkSizeArray[0] = ethashDAGSize / 64; mEthashGlobalWorkSizeArray[0] /= 8; if (mEthashGlobalWorkSizeArray[0] % mEthashLocalWorkSizeArray[0] > 0) { mEthashGlobalWorkSizeArray[0] += mEthashLocalWorkSizeArray[0] - mEthashGlobalWorkSizeArray[0] % mEthashLocalWorkSizeArray[0]; } ComputeBuffer <byte> DAGCacheBuffer = new ComputeBuffer <byte>(Context, ComputeMemoryFlags.ReadOnly, cache.GetData().Length); fixed(byte *p = cache.GetData()) Queue.Write <byte>(DAGCacheBuffer, true, 0, cache.GetData().Length, (IntPtr)p, null); ethashDAGBuffer = new ComputeBuffer <byte>(Context, ComputeMemoryFlags.ReadWrite, mEthashGlobalWorkSizeArray[0] * 8 * 64 /* ethashDAGSize */); // With this, we can remove a conditional statement in the DAG kernel. MemoryUsage += DAGCacheBuffer.Size + ethashDAGBuffer.Size; DAGKernel.SetValueArgument <UInt32>(0, 0); DAGKernel.SetMemoryArgument(1, DAGCacheBuffer); DAGKernel.SetMemoryArgument(2, ethashDAGBuffer); DAGKernel.SetValueArgument <UInt32>(3, (UInt32)cache.GetData().Length / 64); DAGKernel.SetValueArgument <UInt32>(4, 0xffffffffu); for (long start = 0; start < ethashDAGSize / 64; start += mEthashGlobalWorkSizeArray[0]) { mEthashGlobalWorkOffsetArray[0] = start; Queue.Execute(DAGKernel, mEthashGlobalWorkOffsetArray, mEthashGlobalWorkSizeArray, mEthashLocalWorkSizeArray, null); Queue.Finish(); if (Stopped || Stratum.GetJob() == null || !Stratum.GetJob().ID.Equals(ethashJobID)) { break; } } MemoryUsage -= DAGCacheBuffer.Size; DAGCacheBuffer.Dispose(); if (Stopped || Stratum.GetJob() == null || !Stratum.GetJob().ID.Equals(ethashJobID)) { break; } sw.Stop(); MainForm.Logger("Generated DAG for Epoch #" + ethashEpoch + " (" + (long)sw.Elapsed.TotalMilliseconds + "ms)."); } consoleUpdateStopwatch.Start(); while (!Stopped && Stratum.GetJob() != null && Stratum.GetJob().ID.Equals(ethashJobID) && Stratum.PoolExtranonce.Equals(ethashPoolExtranonce)) { MarkAsAlive(); // Get a new local extranonce if necessary. if ((ethashStartNonce & (0xfffffffffffffffful >> (ethashExtranonceByteArray.Length * 8 + 8)) + (ulong)mEthashGlobalWorkSizeArray[0]) >= ((ulong)0x1 << (64 - (ethashExtranonceByteArray.Length * 8 + 8)))) { break; } UInt64 target = (UInt64)((double)0xffff0000U / ethashDifficulty); searchKernel.SetMemoryArgument(0, ethashOutputBuffer); // g_output searchKernel.SetMemoryArgument(1, ethashHeaderBuffer); // g_header searchKernel.SetMemoryArgument(2, ethashDAGBuffer); // _g_dag searchKernel.SetValueArgument <UInt32>(3, (UInt32)(ethashDAGSize / 128)); // DAG_SIZE searchKernel.SetValueArgument <UInt64>(4, ethashStartNonce); // start_nonce searchKernel.SetValueArgument <UInt64>(5, target); // target searchKernel.SetValueArgument <UInt32>(6, 0xffffffffu); // isolate System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); ethashOutput[255] = 0; // ethashOutput[255] is used as an atomic counter. Queue.Write <UInt32>(ethashOutputBuffer, true, 0, 256, (IntPtr)ethashOutputPtr, null); mEthashGlobalWorkOffsetArray[0] = 0; Queue.Execute(searchKernel, mEthashGlobalWorkOffsetArray, mEthashGlobalWorkSizeArray, mEthashLocalWorkSizeArray, null); Queue.Read <UInt32>(ethashOutputBuffer, true, 0, 256, (IntPtr)ethashOutputPtr, null); if (Stratum.GetJob() != null && Stratum.GetJob().ID.Equals(ethashJobID)) { for (int i = 0; i < ethashOutput[255]; ++i) { Stratum.Submit(Device, ethashWork.GetJob(), ethashStartNonce + (UInt64)ethashOutput[i]); } } ethashStartNonce += (UInt64)mEthashGlobalWorkSizeArray[0]; sw.Stop(); Speed = ((double)mEthashGlobalWorkSizeArray[0]) / sw.Elapsed.TotalSeconds; Device.TotalHashesPrimaryAlgorithm += (double)mEthashGlobalWorkSizeArray[0]; if (consoleUpdateStopwatch.ElapsedMilliseconds >= 10 * 1000) { MainForm.Logger("Device #" + DeviceIndex + " (Ethash): " + String.Format("{0:N2} Mh/s", Speed / (1000000))); consoleUpdateStopwatch.Restart(); } } } } catch (Exception ex) { MainForm.Logger("Exception in miner thread: " + ex.Message + ex.StackTrace); Speed = 0; if (UnrecoverableException.IsUnrecoverableException(ex)) { this.UnrecoverableException = new UnrecoverableException(ex, Device); Stop(); } else { MainForm.Logger("Restarting miner thread..."); System.Threading.Thread.Sleep(Parameters.WaitTimeForRestartingMinerThreadInMilliseconds); } } finally { if (ethashDAGBuffer != null) { MemoryUsage -= ethashDAGBuffer.Size; ethashDAGBuffer.Dispose(); ethashDAGBuffer = null; } } } } 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; } }
override unsafe protected void MinerThread() { ComputeProgram program = null; try { Random r = new Random(); MarkAsAlive(); MainForm.Logger("Miner thread for Device #" + DeviceIndex + " started."); program = BuildProgram( "lbry", mLbryLocalWorkSizeArray[0], "-O1 -DITERATIONS=" + mIterations, "-DITERATIONS=" + mIterations, "-DITERATIONS=" + mIterations); using (var lbrySearchKernel = program.CreateKernel("search_combined")) using (var lbryInputBuffer = new ComputeBuffer <byte>(Context, ComputeMemoryFlags.ReadOnly, 112)) using (var lbryOutputBuffer = new ComputeBuffer <UInt32>(Context, ComputeMemoryFlags.ReadWrite, lbryOutputSize)) fixed(long *lbryGlobalWorkOffsetArrayPtr = mLbryGlobalWorkOffsetArray) fixed(long *lbryGlobalWorkSizeArrayPtr = mLbryGlobalWorkSizeArray) fixed(long *lbryLocalWorkSizeArrayPtr = mLbryLocalWorkSizeArray) fixed(byte *lbryInputPtr = mLbryInput) fixed(UInt32 * lbryOutputPtr = mLbryOutput) while (!Stopped) { MarkAsAlive(); try { lbrySearchKernel.SetMemoryArgument(0, lbryInputBuffer); lbrySearchKernel.SetMemoryArgument(1, lbryOutputBuffer); // Wait for the first lbryJob 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 lbryJob."); } System.Diagnostics.Stopwatch consoleUpdateStopwatch = new System.Diagnostics.Stopwatch(); LbryStratum.Work lbryWork; LbryStratum.Job lbryJob; while (!Stopped && (lbryWork = Stratum.GetWork()) != null && (lbryJob = lbryWork.Job) != null) { MarkAsAlive(); Array.Copy(lbryWork.Blob, mLbryInput, 112); UInt32 lbryStartNonce = (UInt32)(r.Next(0, int.MaxValue)); UInt64 lbryTarget = (UInt64)((double)0xffff0000UL / (Stratum.Difficulty / 256)); lbrySearchKernel.SetValueArgument <UInt64>(3, lbryTarget); Queue.Write <byte>(lbryInputBuffer, true, 0, 112, (IntPtr)lbryInputPtr, null); consoleUpdateStopwatch.Start(); while (!Stopped && Stratum.GetJob() != null && Stratum.GetJob().Equals(lbryJob)) { System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); MarkAsAlive(); lbrySearchKernel.SetValueArgument <UInt32>(2, lbryStartNonce); // Get a new local extranonce if necessary. if (0xffffffffu - lbryStartNonce < (UInt32)mLbryGlobalWorkSizeArray[0] * mIterations) { break; } mLbryOutput[255] = 0; // mLbryOutput[255] is used as an atomic counter. Queue.Write <UInt32>(lbryOutputBuffer, true, 0, lbryOutputSize, (IntPtr)lbryOutputPtr, null); Queue.Execute(lbrySearchKernel, mLbryGlobalWorkOffsetArray, mLbryGlobalWorkSizeArray, mLbryLocalWorkSizeArray, null); Queue.Read <UInt32>(lbryOutputBuffer, true, 0, lbryOutputSize, (IntPtr)lbryOutputPtr, null); if (Stratum.GetJob() != null && Stratum.GetJob().Equals(lbryJob)) { for (int i = 0; i < mLbryOutput[255]; ++i) { String result = ""; for (int j = 0; j < 8; ++j) { UInt32 word = mLbryOutput[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, lbryWork, mLbryOutput[i], result); } } lbryStartNonce += (UInt32)mLbryGlobalWorkSizeArray[0] * (uint)mIterations; sw.Stop(); Speed = ((double)mLbryGlobalWorkSizeArray[0]) / sw.Elapsed.TotalSeconds * mIterations; Device.TotalHashesPrimaryAlgorithm += (double)mLbryGlobalWorkSizeArray[0] * mIterations; if (consoleUpdateStopwatch.ElapsedMilliseconds >= 10 * 1000) { MainForm.Logger("Device #" + DeviceIndex + ": " + String.Format("{0:N2} Mh/s (Lbry)", Speed / 1000000)); 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; } } }
private void StreamReaderThread() { Thread.CurrentThread.Priority = ThreadPriority.AboveNormal; int errorCount = 0; UnrecoverableException = null; do { try { System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); try { mMutex.WaitOne(5000); } catch (Exception) { } mClient = new TcpClient(ServerAddress, ServerPort); mStream = mClient.GetStream(); mStreamReader = new StreamReader(mStream, System.Text.Encoding.ASCII, false, 65536); mStreamWriter = new StreamWriter(mStream, System.Text.Encoding.ASCII, 65536); mStreamReader.BaseStream.ReadTimeout = 3 * 60 * 1000; mStreamWriter.BaseStream.WriteTimeout = 10 * 1000; mReconnectionRequested = false; try { mMutex.ReleaseMutex(); } catch (Exception) { } Authorize(); while (!Stopped && !mReconnectionRequested) { string line; try { line = mStreamReader.ReadLine(); } catch (Exception) { throw new StratumServerUnavailableException(); } if (line == null) { throw new StratumServerUnavailableException(); } if (Stopped) { break; } if (line != "") { ProcessLine(line); } if (sw.ElapsedMilliseconds >= 60 * 60 * 1000) { mReconnectionRequested = true; } } } catch (UnrecoverableException ex) { this.UnrecoverableException = ex; } catch (Exception ex) { MainForm.Logger("Exception in Stratum.StreamReaderThread(): " + ex.ToString()); if (UnrecoverableException.IsUnrecoverableException(ex)) { this.UnrecoverableException = new UnrecoverableException(ex.Message); } else if (++errorCount < 4) { MainForm.Logger("Reconnecting to the server..."); System.Threading.Thread.Sleep(5000); } else { this.UnrecoverableException = new StratumServerUnavailableException(); } } try { mClient.Close(); mClient = null; } catch (Exception) { } } while (!Stopped && UnrecoverableException == null); }
override unsafe protected void MinerThread() { Random r = new Random(); MarkAsAlive(); MainForm.Logger("Miner thread for Device #" + DeviceIndex + " started."); BuildPascalProgram(); fixed(long *pascalGlobalWorkOffsetArrayPtr = mPascalGlobalWorkOffsetArray) fixed(long *pascalGlobalWorkSizeArrayPtr = mPascalGlobalWorkSizeArray) fixed(long *pascalLocalWorkSizeArrayPtr = mPascalLocalWorkSizeArray) fixed(byte *pascalMidstatePtr = mPascalMidstate) fixed(byte *pascalInputPtr = mPascalInput) fixed(UInt32 * pascalOutputPtr = mPascalOutput) while (!Stopped) { MarkAsAlive(); try { mPascalSearchKernel.SetMemoryArgument(0, mPascalInputBuffer); mPascalSearchKernel.SetMemoryArgument(1, mPascalOutputBuffer); mPascalSearchKernel.SetMemoryArgument(4, mPascalMidstateBuffer); // Wait for the first PascalJob to arrive. int elapsedTime = 0; while ((mPascalStratum == null || mPascalStratum.GetJob() == null) && elapsedTime < 60000) { Thread.Sleep(100); elapsedTime += 100; } if (mPascalStratum == null || mPascalStratum.GetJob() == null) { throw new TimeoutException("Stratum server failed to send a new PascalJob."); } System.Diagnostics.Stopwatch consoleUpdateStopwatch = new System.Diagnostics.Stopwatch(); PascalStratum.Work pascalWork; while (!Stopped && (pascalWork = mPascalStratum.GetWork()) != null) { MarkAsAlive(); var pascalJob = pascalWork.Job; Array.Copy(pascalWork.Blob, mPascalInput, sPascalInputSize); CalculatePascalMidState(); Queue.Write <byte>(mPascalMidstateBuffer, true, 0, sPascalMidstateSize, (IntPtr)pascalMidstatePtr, null); UInt32 pascalStartNonce = (UInt32)(r.Next(0, int.MaxValue)); UInt64 PascalTarget = (UInt64)((double)0xffff0000UL / mPascalStratum.Difficulty); mPascalSearchKernel.SetValueArgument <UInt64>(3, PascalTarget); Queue.Write <byte>(mPascalInputBuffer, true, 0, sPascalInputSize, (IntPtr)pascalInputPtr, null); consoleUpdateStopwatch.Start(); while (!Stopped && mPascalStratum.GetJob().Equals(pascalJob)) { System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); MarkAsAlive(); mPascalSearchKernel.SetValueArgument <UInt32>(2, pascalStartNonce); // Get a new local extranonce if necessary. if (0xffffffffu - pascalStartNonce < (UInt32)mPascalGlobalWorkSizeArray[0]) { break; } mPascalOutput[255] = 0; // mPascalOutput[255] is used as an atomic counter. Queue.Write <UInt32>(mPascalOutputBuffer, true, 0, sPascalOutputSize, (IntPtr)pascalOutputPtr, null); Queue.Execute(mPascalSearchKernel, mPascalGlobalWorkOffsetArray, mPascalGlobalWorkSizeArray, mPascalLocalWorkSizeArray, null); Queue.Read <UInt32>(mPascalOutputBuffer, true, 0, sPascalOutputSize, (IntPtr)pascalOutputPtr, null); if (mPascalStratum.GetJob().Equals(pascalJob)) { for (int i = 0; i < mPascalOutput[255]; ++i) { mPascalStratum.Submit(GatelessGateDevice, pascalWork, mPascalOutput[i]); } } pascalStartNonce += (UInt32)mPascalGlobalWorkSizeArray[0]; sw.Stop(); Speed = ((double)mPascalGlobalWorkSizeArray[0]) / sw.Elapsed.TotalSeconds; if (consoleUpdateStopwatch.ElapsedMilliseconds >= 10 * 1000) { MainForm.Logger("Device #" + DeviceIndex + ": " + String.Format("{0:N2} Mh/s (Pascal)", Speed / 1000000)); 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(); }
override unsafe protected void MinerThread() { Random r = new Random(); MarkAsAlive(); MainForm.Logger("Miner thread for Device #" + DeviceIndex + " started."); BuildNeoScryptProgram(); fixed(long *neoscryptGlobalWorkOffsetArrayPtr = mNeoScryptGlobalWorkOffsetArray) fixed(long *neoscryptGlobalWorkSizeArrayPtr = mNeoScryptGlobalWorkSizeArray) fixed(long *neoscryptLocalWorkSizeArrayPtr = mNeoScryptLocalWorkSizeArray) fixed(byte *neoscryptInputPtr = mNeoScryptInput) fixed(UInt32 * neoscryptOutputPtr = mNeoScryptOutput) using (ComputeBuffer <byte> mNeoScryptGlobalCacheBuffer = new ComputeBuffer <byte>(Context, ComputeMemoryFlags.ReadWrite, (mNeoScryptGlobalWorkSizeArray[0] * 32768))) while (!Stopped) { MarkAsAlive(); try { mNeoScryptSearchKernel.SetMemoryArgument(0, mNeoScryptInputBuffer); mNeoScryptSearchKernel.SetMemoryArgument(1, mNeoScryptOutputBuffer); mNeoScryptSearchKernel.SetMemoryArgument(2, mNeoScryptGlobalCacheBuffer); // Wait for the first NeoScryptJob to arrive. int elapsedTime = 0; while ((mNeoScryptStratum == null || mNeoScryptStratum.GetJob() == null) && elapsedTime < 60000) { Thread.Sleep(100); elapsedTime += 100; } if (mNeoScryptStratum == null || mNeoScryptStratum.GetJob() == null) { throw new TimeoutException("Stratum server failed to send a new job."); } System.Diagnostics.Stopwatch consoleUpdateStopwatch = new System.Diagnostics.Stopwatch(); NeoScryptStratum.Work neoscryptWork; while (!Stopped && (neoscryptWork = mNeoScryptStratum.GetWork()) != null) { MarkAsAlive(); var neoscryptJob = neoscryptWork.Job; Array.Copy(neoscryptWork.Blob, mNeoScryptInput, sNeoScryptInputSize); UInt32 neoscryptStartNonce = (UInt32)(r.Next(0, int.MaxValue)); Queue.Write <byte>(mNeoScryptInputBuffer, true, 0, sNeoScryptInputSize, (IntPtr)neoscryptInputPtr, null); consoleUpdateStopwatch.Start(); while (!Stopped && mNeoScryptStratum.GetJob().Equals(neoscryptJob)) { System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); MarkAsAlive(); UInt32 NeoScryptTarget = (UInt32)((double)0xffff0000U / (mNeoScryptStratum.Difficulty * 65536)); mNeoScryptSearchKernel.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>(mNeoScryptOutputBuffer, true, 0, sNeoScryptOutputSize, (IntPtr)neoscryptOutputPtr, null); Queue.Execute(mNeoScryptSearchKernel, mNeoScryptGlobalWorkOffsetArray, mNeoScryptGlobalWorkSizeArray, mNeoScryptLocalWorkSizeArray, null); Queue.Read <UInt32>(mNeoScryptOutputBuffer, true, 0, sNeoScryptOutputSize, (IntPtr)neoscryptOutputPtr, null); if (mNeoScryptStratum.GetJob().Equals(neoscryptJob)) { for (int i = 0; i < mNeoScryptOutput[255]; ++i) { mNeoScryptStratum.Submit(GatelessGateDevice, neoscryptWork, mNeoScryptOutput[i]); } } neoscryptStartNonce += (UInt32)mNeoScryptGlobalWorkSizeArray[0]; sw.Stop(); Speed = ((double)mNeoScryptGlobalWorkSizeArray[0]) / sw.Elapsed.TotalSeconds; 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, GatelessGateDevice); Stop(); } } Speed = 0; if (!Stopped) { MainForm.Logger("Restarting miner thread..."); System.Threading.Thread.Sleep(5000); } } MarkAsDone(); }
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; } } }
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(); }
override unsafe protected void MinerThread() { Random r = new Random(); MarkAsAlive(); MainForm.Logger("Miner thread for Device #" + DeviceIndex + " started."); BuildLbryProgram(); fixed(long *lbryGlobalWorkOffsetArrayPtr = mLbryGlobalWorkOffsetArray) fixed(long *lbryGlobalWorkSizeArrayPtr = mLbryGlobalWorkSizeArray) fixed(long *lbryLocalWorkSizeArrayPtr = mLbryLocalWorkSizeArray) fixed(byte *lbryInputPtr = mLbryInput) fixed(UInt32 * lbryOutputPtr = mLbryOutput) while (!Stopped) { MarkAsAlive(); try { mLbrySearchKernel.SetMemoryArgument(0, mLbryInputBuffer); mLbrySearchKernel.SetMemoryArgument(1, mLbryOutputBuffer); // Wait for the first lbryJob to arrive. int elapsedTime = 0; while ((mLbryStratum == null || mLbryStratum.GetJob() == null) && elapsedTime < 60000) { Thread.Sleep(100); elapsedTime += 100; } if (mLbryStratum == null || mLbryStratum.GetJob() == null) { throw new TimeoutException("Stratum server failed to send a new lbryJob."); } System.Diagnostics.Stopwatch consoleUpdateStopwatch = new System.Diagnostics.Stopwatch(); LbryStratum.Work lbryWork; while (!Stopped && (lbryWork = mLbryStratum.GetWork()) != null) { MarkAsAlive(); var lbryJob = lbryWork.Job; Array.Copy(lbryWork.Blob, mLbryInput, 112); UInt32 lbryStartNonce = (UInt32)(r.Next(0, int.MaxValue)); UInt64 lbryTarget = (UInt64)((double)0xffff0000UL / (mLbryStratum.Difficulty / 256)); mLbrySearchKernel.SetValueArgument <UInt64>(3, lbryTarget); Queue.Write <byte>(mLbryInputBuffer, true, 0, 112, (IntPtr)lbryInputPtr, null); consoleUpdateStopwatch.Start(); while (!Stopped && mLbryStratum.GetJob().Equals(lbryJob)) { System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); MarkAsAlive(); mLbrySearchKernel.SetValueArgument <UInt32>(2, lbryStartNonce); // Get a new local extranonce if necessary. if (0xffffffffu - lbryStartNonce < (UInt32)mLbryGlobalWorkSizeArray[0] * mIterations) { break; } mLbryOutput[255] = 0; // mLbryOutput[255] is used as an atomic counter. Queue.Write <UInt32>(mLbryOutputBuffer, true, 0, lbryOutputSize, (IntPtr)lbryOutputPtr, null); Queue.Execute(mLbrySearchKernel, mLbryGlobalWorkOffsetArray, mLbryGlobalWorkSizeArray, mLbryLocalWorkSizeArray, null); Queue.Read <UInt32>(mLbryOutputBuffer, true, 0, lbryOutputSize, (IntPtr)lbryOutputPtr, null); if (mLbryStratum.GetJob().Equals(lbryJob)) { for (int i = 0; i < mLbryOutput[255]; ++i) { String result = ""; for (int j = 0; j < 8; ++j) { UInt32 word = mLbryOutput[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)); } mLbryStratum.Submit(GatelessGateDevice, lbryWork, mLbryOutput[i], result); } } lbryStartNonce += (UInt32)mLbryGlobalWorkSizeArray[0] * (uint)mIterations; sw.Stop(); Speed = ((double)mLbryGlobalWorkSizeArray[0]) / sw.Elapsed.TotalSeconds * mIterations; if (consoleUpdateStopwatch.ElapsedMilliseconds >= 10 * 1000) { MainForm.Logger("Device #" + DeviceIndex + ": " + String.Format("{0:N2} Mh/s (Lbry)", Speed / 1000000)); 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(); }