Skip to content

Commit

Permalink
Merge pull request #2871 from nicehash/NL-2238_excavator_randomx
Browse files Browse the repository at this point in the history
NL-2238 excavator randomx
  • Loading branch information
object05 committed Mar 20, 2023
2 parents 43122a9 + 7108d54 commit b01b6c9
Show file tree
Hide file tree
Showing 7 changed files with 185 additions and 124 deletions.
38 changes: 17 additions & 21 deletions src/Miners/Excavator/CmdConfig.cs
Expand Up @@ -41,7 +41,7 @@ class CommandList
ObjectCreationHandling = ObjectCreationHandling.Replace
};

public static string CreateTemplate(IEnumerable<string> gpuUuids, string algorithmName)
public static string CreateTemplate(IEnumerable<int> gpuUuids, string algorithmName)
{
return CreateDefaultTemplateAndCreateCMD("__SUBSCRIBE_PARAM_LOCATION__", "__SUBSCRIBE_PARAM_USERNAME__", gpuUuids, algorithmName);
}
Expand All @@ -51,18 +51,22 @@ public static string CommandFileTemplatePath(string pluginUUID)
return Paths.MinerPluginsPath(pluginUUID, "internals", "CommandLineTemplate.json");
}

private static List<Command> CreateInitialCommands(string subscribeLocation, string subscribeUsername, IEnumerable<string> gpuUuids, string algorithmName)
private static List<Command> CreateInitialCommands(string subscribeLocation, string subscribeUsername, IEnumerable<int> excavatorIds, string algorithmName)
{
var initialCommands = new List<Command>
{
new Command { Id = 1, Method = "subscribe", Params = new List<string>{ subscribeLocation, subscribeUsername } },
new Command { Id = 2, Method = "algorithm.add", Params = new List<string>{ algorithmName.ToLower() } },
};
initialCommands.AddRange(gpuUuids.Select((gpu, index) => new Command { Id = index + 3, Method = "worker.add", Params = new List<string> { algorithmName.ToLower(), gpu } }));
if (algorithmName == "randomx")
{
initialCommands.AddRange(excavatorIds.Select((dev, index) => new Command { Id = index + 3, Method = "worker.add", Params = new List<string> { algorithmName, dev.ToString(), "NTHREADS=0", "HIGHPRIORITY=0", "USELARGEPAGE=1", "USEMSR=1" } }));
}
else initialCommands.AddRange(excavatorIds.Select((dev, index) => new Command { Id = index + 3, Method = "worker.add", Params = new List<string> { algorithmName.ToLower(), dev.ToString() } }));
return initialCommands;
}

private static string CreateDefaultTemplateAndCreateCMD(string subscribeLocation, string subscribeUsername, IEnumerable<string> gpuUuids, string algorithmName)
private static string CreateDefaultTemplateAndCreateCMD(string subscribeLocation, string subscribeUsername, IEnumerable<int> excavatorIds, string algorithmName)
{
try
{
Expand All @@ -71,7 +75,7 @@ private static string CreateDefaultTemplateAndCreateCMD(string subscribeLocation
new CommandList
{
Time = 0,
Commands = CreateInitialCommands(subscribeLocation, subscribeUsername, gpuUuids, algorithmName),
Commands = CreateInitialCommands(subscribeLocation, subscribeUsername, excavatorIds, algorithmName),
},
new CommandList
{
Expand All @@ -88,15 +92,15 @@ private static string CreateDefaultTemplateAndCreateCMD(string subscribeLocation
}
}
private static string[] _invalidTemplateMethods = new string[] { "subscribe", "algorithm.add", "worker.add" };
private static string ParseTemplateFileAndCreateCMD(string templateFilePath, IEnumerable<string> gpuUuids, string subscribeLocation, string subscribeUsername, string algorithmName)
private static string ParseTemplateFileAndCreateCMD(string templateFilePath, IEnumerable<int> excavatorIds, string subscribeLocation, string subscribeUsername, string algorithmName)
{
if (!File.Exists(templateFilePath)) return null;
try
{
var template = JsonConvert.DeserializeObject<List<CommandList>>(File.ReadAllText(templateFilePath), _jsonSettings);
var validCmds = template
.Where(cmd => cmd.Commands.All(c => !_invalidTemplateMethods.Contains(c.Method)))
.Select(cmd => (cmd, commands: cmd.Commands.Where(c => IsValidSessionCommand(c, gpuUuids)).ToList()))
.Select(cmd => (cmd, commands: cmd.Commands.ToList()))
.Where(p => p.commands.Any())
.ToArray();
foreach (var (cmd, commands) in validCmds)
Expand All @@ -108,7 +112,7 @@ private static string ParseTemplateFileAndCreateCMD(string templateFilePath, IEn
new CommandList
{
Time = 0,
Commands = CreateInitialCommands(subscribeLocation, subscribeUsername, gpuUuids, algorithmName),
Commands = CreateInitialCommands(subscribeLocation, subscribeUsername, excavatorIds, algorithmName),
},
};
if (validCmds.Any()) commandListTemplate.AddRange(validCmds.Select(p => p.cmd));
Expand All @@ -121,21 +125,13 @@ private static string ParseTemplateFileAndCreateCMD(string templateFilePath, IEn
}
}

private static bool IsValidSessionCommand(Command command, IEnumerable<string> gpuUuids)
{
var anyMissingGpuUuidParams = command.Params
.Where(p => p.StartsWith("GPU"))
.Any(pGpu => !gpuUuids.Contains(pGpu));
return !anyMissingGpuUuidParams;
}

private static string CreateCommandWithTemplate(string subscribeLocation, string subscribeUsername, IEnumerable<string> gpuUuids, string templateFilePath, string algorithmName)
private static string CreateCommandWithTemplate(string subscribeLocation, string subscribeUsername, IEnumerable<int> excavatorIds, string templateFilePath, string algorithmName)
{
var template = ParseTemplateFileAndCreateCMD(templateFilePath, gpuUuids, subscribeLocation, subscribeUsername, algorithmName);
var template = ParseTemplateFileAndCreateCMD(templateFilePath, excavatorIds, subscribeLocation, subscribeUsername, algorithmName);
if (template == null)
{
Logger.Warn("Excavator.CmdConfig", "Template file not found, using default!");
template = CreateDefaultTemplateAndCreateCMD(subscribeLocation, subscribeUsername, gpuUuids, algorithmName);
template = CreateDefaultTemplateAndCreateCMD(subscribeLocation, subscribeUsername, excavatorIds, algorithmName);
}
return template;
}
Expand All @@ -147,11 +143,11 @@ private static string GetServiceLocation(string miningLocation)
return $"nhmp.auto.nicehash.com:443";
}

public static string CmdJSONString(string pluginUUID, string _miningLocation, string username, string algorithmName, params string[] uuids) {
public static string CmdJSONString(string pluginUUID, string _miningLocation, string username, string algorithmName, params int[] excavatorIds) {
var miningLocation = GetMiningLocation(_miningLocation);
var templatePath = CommandFileTemplatePath(pluginUUID);
var miningServiceLocation = GetServiceLocation(miningLocation);
var command = CreateCommandWithTemplate(miningServiceLocation, username, uuids, templatePath, algorithmName);
var command = CreateCommandWithTemplate(miningServiceLocation, username, excavatorIds, templatePath, algorithmName);
if (command == null) Logger.Error("Excavator.CmdConfig", "command is NULL");
return command;
}
Expand Down
111 changes: 109 additions & 2 deletions src/Miners/Excavator/DevicesListParser.cs
@@ -1,7 +1,114 @@
namespace Excavator
using NHM.Common;
using NHM.Common.Device;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Excavator
{
internal class DevicesListParser
{
// TODO in case of NVIDIA SLI execute device cross ref
private static string[] _keywords = new string[] { "DeviceId:", "BusId:" };

private static bool KeepLine(string line)
{
if (string.IsNullOrEmpty(line) || string.IsNullOrWhiteSpace(line)) return false;
var words = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
return words.Any(_keywords.Contains);
}


private static int? NumberAfterPattern(string pattern, string line)
{
try
{
var index = line?.IndexOf(pattern) ?? -1;
if (index < 0) return null;
var numericChars = line
.Substring(index + pattern.Length)
.SkipWhile(c => !char.IsDigit(c))
.TakeWhile(char.IsDigit)
.ToArray();
var numberStr = new string(numericChars);
if (int.TryParse(numberStr, out var number)) return number;
}
catch
{ }
return null;
}

private static int[] ChunkToGPU_PCIe_Pair(string[] chunk)
{
return _keywords.Zip(chunk, (pattern, line) => (pattern, line))
.Select(p => NumberAfterPattern(p.pattern, p.line))
.Where(num => num.HasValue)
.Select(num => num.Value)
.ToArray();
}

public static IEnumerable<(string uuid, int minerGpuId)> ParseExcavatorOutput(string output, IEnumerable<BaseDevice> baseDevices)
{
try
{
var gpus = baseDevices
.Where(dev => dev is IGpuDevice)
.Cast<IGpuDevice>()
.ToArray();

var mappedDevices = output.Split(new[] { "\r\n", "\n", Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)
.Where(KeepLine)
.Select((line, index) => (line, index))
.GroupBy(p => p.index / _keywords.Length)
.Select(g => g.Select(p => p.line).ToArray())
.Select(ChunkToGPU_PCIe_Pair)
.Where(nums => nums.Length == 2)
.Select(nums => (minerGpuId: nums[0], pcie: nums[1]))
.Select(p => (gpu: gpus.FirstOrDefault(gpu => gpu.PCIeBusID == p.pcie), p.minerGpuId))
.Where(p => p.gpu != null)
.Select(p => (uuid: p.gpu.UUID, p.minerGpuId))
.ToArray();
return mappedDevices;
}
catch (Exception e)
{
Logger.Error("ExcavatorPlugin", $"DevicesListParser error: {e.Message}");
return Enumerable.Empty<(string uuid, int minerGpuId)>();
}
}

public static (string uuid, int minerCpuId) ParseExcavatorOutputCPU(string output, IEnumerable<BaseDevice> baseDevices)
{
try
{
var cpus = baseDevices
.Where(dev => dev is CPUDevice)
.Cast<CPUDevice>()
.ToArray();

var mappedDevices = new Dictionary<string, int>();
var tmpIndexes = new List<int>();

var lines = output.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries);
if (lines.Count() != 0)
{
foreach (var line in lines)
{
if (!line.Contains("DeviceId:")) continue;
var id = line.Split(':');
var pciId = id[1];
tmpIndexes.Add(Convert.ToInt32(pciId));
}
}
var cpu = cpus.FirstOrDefault().UUID;
var index = tmpIndexes.Last();

return (cpu, index);
}
catch (Exception e)
{
Logger.Error("ExcavatorPlugin", $"DevicesListParser error: {e.Message}");
return ( "", -1);
}
}
}
}
35 changes: 17 additions & 18 deletions src/Miners/Excavator/Excavator.cs
Expand Up @@ -18,8 +18,8 @@ namespace Excavator
{
public class Excavator : MinerBase, IAfterStartMining, IDisposable
{
protected readonly Dictionary<string, string> _mappedDeviceIds = new Dictionary<string, string>();
public Excavator(string uuid, Dictionary<string, string> mappedIDs) : base(uuid)
protected readonly Dictionary<string, int> _mappedDeviceIds = new Dictionary<string, int>();
public Excavator(string uuid, Dictionary<string, int> mappedIDs) : base(uuid)
{
_mappedDeviceIds = mappedIDs;
}
Expand Down Expand Up @@ -112,14 +112,14 @@ private async Task<ApiData> GetMinerStatsDataAsyncPrivate(CancellationToken stop
var response = await ExecuteCommand(speeds, stop);
ad.ApiResponse = response;
var summary = JsonConvert.DeserializeObject<JsonApiResponse>(response);
var gpus = _miningPairs.Select(pair => _mappedDeviceIds[pair.Device.UUID]);
var devs = _miningPairs.Select(pair => _mappedDeviceIds[pair.Device.UUID]);
var perDeviceSpeedInfo = new Dictionary<string, IReadOnlyList<(AlgorithmType type, double speed)>>();
var perDevicePowerInfo = new Dictionary<string, int>();
foreach (var gpu in gpus)
foreach (var dev in devs)
{
var nhmGPUuuid = _mappedDeviceIds.Where(uuid => uuid.Value == gpu).Select(item => item.Key).FirstOrDefault();
var speed = summary.workers.Where(w => w.device_uuid == gpu).SelectMany(w => w.algorithms.Select(a => a.speed)).Sum();
perDeviceSpeedInfo.Add(nhmGPUuuid, new List<(AlgorithmType type, double speed)>() { (_algorithmType, speed) });
var nhmDevUuid = _mappedDeviceIds.Where(uuid => uuid.Value == dev).Select(item => item.Key).FirstOrDefault();
var speed = summary.workers.Where(w => w.device_id == dev).SelectMany(w => w.algorithms.Select(a => a.speed)).Sum();
perDeviceSpeedInfo.Add(nhmDevUuid, new List<(AlgorithmType type, double speed)>() { (_algorithmType, speed) });
}
ad.PowerUsageTotal = 0;
ad.AlgorithmSpeedsPerDevice = perDeviceSpeedInfo;
Expand All @@ -134,29 +134,27 @@ private async Task<ApiData> GetMinerStatsDataAsyncPrivate(CancellationToken stop
}

protected override void Init() { }
private (IEnumerable<string> uuids, IEnumerable<int> ids) GetUUIDsAndIDs(IEnumerable<MiningPair> pairs)
private (IEnumerable<int> excavatorids, IEnumerable<int> ids) GetUUIDsAndIDs(IEnumerable<MiningPair> pairs)
{
var devices = pairs
.Select(p => p.Device)
.Where(dev => dev is IGpuDevice);
.Select(p => p.Device);
if (devices.Any())
{
var devs = devices.Cast<IGpuDevice>();
var uuids = devs.Select(gpu => _mappedDeviceIds[gpu.UUID]);
var ids = devs.Select(gpu => gpu.PCIeBusID);
return (uuids, ids);
var excavatorIds = devices.Select(dev => _mappedDeviceIds[dev.UUID]);
var ids = devices.Select(dev => dev.ID);
return (excavatorIds, ids);
}
return (Enumerable.Empty<string>(), Enumerable.Empty<int>());
return (Enumerable.Empty<int>(), Enumerable.Empty<int>());
}

protected override string MiningCreateCommandLine()
{
// API port function might be blocking
_apiPort = GetAvaliablePort();
var (uuids, ids) = GetUUIDsAndIDs(_miningPairs);
var (excavatorIds, ids) = GetUUIDsAndIDs(_miningPairs);
var (_, cwd) = GetBinAndCwdPaths();
var fileName = $"cmd_{string.Join("_", ids)}.json";
var cmdStr = CmdConfig.CmdJSONString(_uuid, _miningLocation, _username, _algorithmType.ToString(), uuids.ToArray());
var fileName = $"cmd_{string.Join("_", excavatorIds)}.json";
var cmdStr = CmdConfig.CmdJSONString(_uuid, _miningLocation, _username, AlgorithmName(_algorithmType), excavatorIds.ToArray());
File.WriteAllText(Path.Combine(cwd, fileName), cmdStr);
var commandLine = $"-wp {_apiPort} -wa \"{_authToken}\" -c {fileName} -m -qx {_extraLaunchParameters}";
return commandLine;
Expand Down Expand Up @@ -268,6 +266,7 @@ public override async Task<BenchmarkResult> StartBenchmark(CancellationToken sto
// determine benchmark time
// settup times
var benchmarkTime = MinerBenchmarkTimeSettings.ParseBenchmarkTime(new List<int> { 20, 40, 60 }, MinerBenchmarkTimeSettings, _miningPairs, benchmarkType); // in seconds
if (_algorithmType == AlgorithmType.RandomXmonero) benchmarkTime = MinerBenchmarkTimeSettings.ParseBenchmarkTime(new List<int> { 60, 80, 100 }, MinerBenchmarkTimeSettings, _miningPairs, benchmarkType);
var maxTicks = MinerBenchmarkTimeSettings.ParseBenchmarkTicks(new List<int> { 1, 3, 9 }, MinerBenchmarkTimeSettings, _miningPairs, benchmarkType);
var maxTicksEnabled = MinerBenchmarkTimeSettings.MaxTicksEnabled;

Expand Down
Expand Up @@ -33,6 +33,13 @@ public partial class ExcavatorPlugin
new SAS(AlgorithmType.KAWPOW) { Enabled = false },
new SAS(AlgorithmType.NeoScrypt),
}
},
{
DeviceType.CPU,
new List<SAS>
{
new SAS(AlgorithmType.RandomXmonero)
}
}
},
AlgorithmNames = new Dictionary<AlgorithmType, string>
Expand All @@ -41,7 +48,8 @@ public partial class ExcavatorPlugin
{ AlgorithmType.EtcHash, "etchash" },
{ AlgorithmType.Autolykos, "autolykos" },
{ AlgorithmType.KAWPOW, "kawpow" },
{ AlgorithmType.NeoScrypt, "neoscrypt" }
{ AlgorithmType.NeoScrypt, "neoscrypt" },
{ AlgorithmType.RandomXmonero, "randomx" }
}
};
}
Expand Down

4 comments on commit b01b6c9

@Jhonby931
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private static List CreateInitialCommands(string subscribeLocation, string subscribeUsername, IEnumerable excavatorIds, string algorithmName)

@Jhonby931
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Help me

@Jhonby931
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tdis program is ok

@Jhonby931
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is good❣️❤️

Please sign in to comment.