Skip to content

Commit b01b6c9

Browse files
authored
Merge pull request #2871 from nicehash/NL-2238_excavator_randomx
NL-2238 excavator randomx
2 parents 43122a9 + 7108d54 commit b01b6c9

File tree

7 files changed

+185
-124
lines changed

7 files changed

+185
-124
lines changed

src/Miners/Excavator/CmdConfig.cs

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class CommandList
4141
ObjectCreationHandling = ObjectCreationHandling.Replace
4242
};
4343

44-
public static string CreateTemplate(IEnumerable<string> gpuUuids, string algorithmName)
44+
public static string CreateTemplate(IEnumerable<int> gpuUuids, string algorithmName)
4545
{
4646
return CreateDefaultTemplateAndCreateCMD("__SUBSCRIBE_PARAM_LOCATION__", "__SUBSCRIBE_PARAM_USERNAME__", gpuUuids, algorithmName);
4747
}
@@ -51,18 +51,22 @@ public static string CommandFileTemplatePath(string pluginUUID)
5151
return Paths.MinerPluginsPath(pluginUUID, "internals", "CommandLineTemplate.json");
5252
}
5353

54-
private static List<Command> CreateInitialCommands(string subscribeLocation, string subscribeUsername, IEnumerable<string> gpuUuids, string algorithmName)
54+
private static List<Command> CreateInitialCommands(string subscribeLocation, string subscribeUsername, IEnumerable<int> excavatorIds, string algorithmName)
5555
{
5656
var initialCommands = new List<Command>
5757
{
5858
new Command { Id = 1, Method = "subscribe", Params = new List<string>{ subscribeLocation, subscribeUsername } },
5959
new Command { Id = 2, Method = "algorithm.add", Params = new List<string>{ algorithmName.ToLower() } },
6060
};
61-
initialCommands.AddRange(gpuUuids.Select((gpu, index) => new Command { Id = index + 3, Method = "worker.add", Params = new List<string> { algorithmName.ToLower(), gpu } }));
61+
if (algorithmName == "randomx")
62+
{
63+
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" } }));
64+
}
65+
else initialCommands.AddRange(excavatorIds.Select((dev, index) => new Command { Id = index + 3, Method = "worker.add", Params = new List<string> { algorithmName.ToLower(), dev.ToString() } }));
6266
return initialCommands;
6367
}
6468

65-
private static string CreateDefaultTemplateAndCreateCMD(string subscribeLocation, string subscribeUsername, IEnumerable<string> gpuUuids, string algorithmName)
69+
private static string CreateDefaultTemplateAndCreateCMD(string subscribeLocation, string subscribeUsername, IEnumerable<int> excavatorIds, string algorithmName)
6670
{
6771
try
6872
{
@@ -71,7 +75,7 @@ private static string CreateDefaultTemplateAndCreateCMD(string subscribeLocation
7175
new CommandList
7276
{
7377
Time = 0,
74-
Commands = CreateInitialCommands(subscribeLocation, subscribeUsername, gpuUuids, algorithmName),
78+
Commands = CreateInitialCommands(subscribeLocation, subscribeUsername, excavatorIds, algorithmName),
7579
},
7680
new CommandList
7781
{
@@ -88,15 +92,15 @@ private static string CreateDefaultTemplateAndCreateCMD(string subscribeLocation
8892
}
8993
}
9094
private static string[] _invalidTemplateMethods = new string[] { "subscribe", "algorithm.add", "worker.add" };
91-
private static string ParseTemplateFileAndCreateCMD(string templateFilePath, IEnumerable<string> gpuUuids, string subscribeLocation, string subscribeUsername, string algorithmName)
95+
private static string ParseTemplateFileAndCreateCMD(string templateFilePath, IEnumerable<int> excavatorIds, string subscribeLocation, string subscribeUsername, string algorithmName)
9296
{
9397
if (!File.Exists(templateFilePath)) return null;
9498
try
9599
{
96100
var template = JsonConvert.DeserializeObject<List<CommandList>>(File.ReadAllText(templateFilePath), _jsonSettings);
97101
var validCmds = template
98102
.Where(cmd => cmd.Commands.All(c => !_invalidTemplateMethods.Contains(c.Method)))
99-
.Select(cmd => (cmd, commands: cmd.Commands.Where(c => IsValidSessionCommand(c, gpuUuids)).ToList()))
103+
.Select(cmd => (cmd, commands: cmd.Commands.ToList()))
100104
.Where(p => p.commands.Any())
101105
.ToArray();
102106
foreach (var (cmd, commands) in validCmds)
@@ -108,7 +112,7 @@ private static string ParseTemplateFileAndCreateCMD(string templateFilePath, IEn
108112
new CommandList
109113
{
110114
Time = 0,
111-
Commands = CreateInitialCommands(subscribeLocation, subscribeUsername, gpuUuids, algorithmName),
115+
Commands = CreateInitialCommands(subscribeLocation, subscribeUsername, excavatorIds, algorithmName),
112116
},
113117
};
114118
if (validCmds.Any()) commandListTemplate.AddRange(validCmds.Select(p => p.cmd));
@@ -121,21 +125,13 @@ private static string ParseTemplateFileAndCreateCMD(string templateFilePath, IEn
121125
}
122126
}
123127

124-
private static bool IsValidSessionCommand(Command command, IEnumerable<string> gpuUuids)
125-
{
126-
var anyMissingGpuUuidParams = command.Params
127-
.Where(p => p.StartsWith("GPU"))
128-
.Any(pGpu => !gpuUuids.Contains(pGpu));
129-
return !anyMissingGpuUuidParams;
130-
}
131-
132-
private static string CreateCommandWithTemplate(string subscribeLocation, string subscribeUsername, IEnumerable<string> gpuUuids, string templateFilePath, string algorithmName)
128+
private static string CreateCommandWithTemplate(string subscribeLocation, string subscribeUsername, IEnumerable<int> excavatorIds, string templateFilePath, string algorithmName)
133129
{
134-
var template = ParseTemplateFileAndCreateCMD(templateFilePath, gpuUuids, subscribeLocation, subscribeUsername, algorithmName);
130+
var template = ParseTemplateFileAndCreateCMD(templateFilePath, excavatorIds, subscribeLocation, subscribeUsername, algorithmName);
135131
if (template == null)
136132
{
137133
Logger.Warn("Excavator.CmdConfig", "Template file not found, using default!");
138-
template = CreateDefaultTemplateAndCreateCMD(subscribeLocation, subscribeUsername, gpuUuids, algorithmName);
134+
template = CreateDefaultTemplateAndCreateCMD(subscribeLocation, subscribeUsername, excavatorIds, algorithmName);
139135
}
140136
return template;
141137
}
@@ -147,11 +143,11 @@ private static string GetServiceLocation(string miningLocation)
147143
return $"nhmp.auto.nicehash.com:443";
148144
}
149145

150-
public static string CmdJSONString(string pluginUUID, string _miningLocation, string username, string algorithmName, params string[] uuids) {
146+
public static string CmdJSONString(string pluginUUID, string _miningLocation, string username, string algorithmName, params int[] excavatorIds) {
151147
var miningLocation = GetMiningLocation(_miningLocation);
152148
var templatePath = CommandFileTemplatePath(pluginUUID);
153149
var miningServiceLocation = GetServiceLocation(miningLocation);
154-
var command = CreateCommandWithTemplate(miningServiceLocation, username, uuids, templatePath, algorithmName);
150+
var command = CreateCommandWithTemplate(miningServiceLocation, username, excavatorIds, templatePath, algorithmName);
155151
if (command == null) Logger.Error("Excavator.CmdConfig", "command is NULL");
156152
return command;
157153
}
Lines changed: 109 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,114 @@
1-
namespace Excavator
1+
using NHM.Common;
2+
using NHM.Common.Device;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
7+
namespace Excavator
28
{
39
internal class DevicesListParser
410
{
5-
// TODO in case of NVIDIA SLI execute device cross ref
11+
private static string[] _keywords = new string[] { "DeviceId:", "BusId:" };
12+
13+
private static bool KeepLine(string line)
14+
{
15+
if (string.IsNullOrEmpty(line) || string.IsNullOrWhiteSpace(line)) return false;
16+
var words = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
17+
return words.Any(_keywords.Contains);
18+
}
19+
20+
21+
private static int? NumberAfterPattern(string pattern, string line)
22+
{
23+
try
24+
{
25+
var index = line?.IndexOf(pattern) ?? -1;
26+
if (index < 0) return null;
27+
var numericChars = line
28+
.Substring(index + pattern.Length)
29+
.SkipWhile(c => !char.IsDigit(c))
30+
.TakeWhile(char.IsDigit)
31+
.ToArray();
32+
var numberStr = new string(numericChars);
33+
if (int.TryParse(numberStr, out var number)) return number;
34+
}
35+
catch
36+
{ }
37+
return null;
38+
}
39+
40+
private static int[] ChunkToGPU_PCIe_Pair(string[] chunk)
41+
{
42+
return _keywords.Zip(chunk, (pattern, line) => (pattern, line))
43+
.Select(p => NumberAfterPattern(p.pattern, p.line))
44+
.Where(num => num.HasValue)
45+
.Select(num => num.Value)
46+
.ToArray();
47+
}
48+
49+
public static IEnumerable<(string uuid, int minerGpuId)> ParseExcavatorOutput(string output, IEnumerable<BaseDevice> baseDevices)
50+
{
51+
try
52+
{
53+
var gpus = baseDevices
54+
.Where(dev => dev is IGpuDevice)
55+
.Cast<IGpuDevice>()
56+
.ToArray();
57+
58+
var mappedDevices = output.Split(new[] { "\r\n", "\n", Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)
59+
.Where(KeepLine)
60+
.Select((line, index) => (line, index))
61+
.GroupBy(p => p.index / _keywords.Length)
62+
.Select(g => g.Select(p => p.line).ToArray())
63+
.Select(ChunkToGPU_PCIe_Pair)
64+
.Where(nums => nums.Length == 2)
65+
.Select(nums => (minerGpuId: nums[0], pcie: nums[1]))
66+
.Select(p => (gpu: gpus.FirstOrDefault(gpu => gpu.PCIeBusID == p.pcie), p.minerGpuId))
67+
.Where(p => p.gpu != null)
68+
.Select(p => (uuid: p.gpu.UUID, p.minerGpuId))
69+
.ToArray();
70+
return mappedDevices;
71+
}
72+
catch (Exception e)
73+
{
74+
Logger.Error("ExcavatorPlugin", $"DevicesListParser error: {e.Message}");
75+
return Enumerable.Empty<(string uuid, int minerGpuId)>();
76+
}
77+
}
78+
79+
public static (string uuid, int minerCpuId) ParseExcavatorOutputCPU(string output, IEnumerable<BaseDevice> baseDevices)
80+
{
81+
try
82+
{
83+
var cpus = baseDevices
84+
.Where(dev => dev is CPUDevice)
85+
.Cast<CPUDevice>()
86+
.ToArray();
87+
88+
var mappedDevices = new Dictionary<string, int>();
89+
var tmpIndexes = new List<int>();
90+
91+
var lines = output.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries);
92+
if (lines.Count() != 0)
93+
{
94+
foreach (var line in lines)
95+
{
96+
if (!line.Contains("DeviceId:")) continue;
97+
var id = line.Split(':');
98+
var pciId = id[1];
99+
tmpIndexes.Add(Convert.ToInt32(pciId));
100+
}
101+
}
102+
var cpu = cpus.FirstOrDefault().UUID;
103+
var index = tmpIndexes.Last();
104+
105+
return (cpu, index);
106+
}
107+
catch (Exception e)
108+
{
109+
Logger.Error("ExcavatorPlugin", $"DevicesListParser error: {e.Message}");
110+
return ( "", -1);
111+
}
112+
}
6113
}
7114
}

src/Miners/Excavator/Excavator.cs

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ namespace Excavator
1818
{
1919
public class Excavator : MinerBase, IAfterStartMining, IDisposable
2020
{
21-
protected readonly Dictionary<string, string> _mappedDeviceIds = new Dictionary<string, string>();
22-
public Excavator(string uuid, Dictionary<string, string> mappedIDs) : base(uuid)
21+
protected readonly Dictionary<string, int> _mappedDeviceIds = new Dictionary<string, int>();
22+
public Excavator(string uuid, Dictionary<string, int> mappedIDs) : base(uuid)
2323
{
2424
_mappedDeviceIds = mappedIDs;
2525
}
@@ -112,14 +112,14 @@ private async Task<ApiData> GetMinerStatsDataAsyncPrivate(CancellationToken stop
112112
var response = await ExecuteCommand(speeds, stop);
113113
ad.ApiResponse = response;
114114
var summary = JsonConvert.DeserializeObject<JsonApiResponse>(response);
115-
var gpus = _miningPairs.Select(pair => _mappedDeviceIds[pair.Device.UUID]);
115+
var devs = _miningPairs.Select(pair => _mappedDeviceIds[pair.Device.UUID]);
116116
var perDeviceSpeedInfo = new Dictionary<string, IReadOnlyList<(AlgorithmType type, double speed)>>();
117117
var perDevicePowerInfo = new Dictionary<string, int>();
118-
foreach (var gpu in gpus)
118+
foreach (var dev in devs)
119119
{
120-
var nhmGPUuuid = _mappedDeviceIds.Where(uuid => uuid.Value == gpu).Select(item => item.Key).FirstOrDefault();
121-
var speed = summary.workers.Where(w => w.device_uuid == gpu).SelectMany(w => w.algorithms.Select(a => a.speed)).Sum();
122-
perDeviceSpeedInfo.Add(nhmGPUuuid, new List<(AlgorithmType type, double speed)>() { (_algorithmType, speed) });
120+
var nhmDevUuid = _mappedDeviceIds.Where(uuid => uuid.Value == dev).Select(item => item.Key).FirstOrDefault();
121+
var speed = summary.workers.Where(w => w.device_id == dev).SelectMany(w => w.algorithms.Select(a => a.speed)).Sum();
122+
perDeviceSpeedInfo.Add(nhmDevUuid, new List<(AlgorithmType type, double speed)>() { (_algorithmType, speed) });
123123
}
124124
ad.PowerUsageTotal = 0;
125125
ad.AlgorithmSpeedsPerDevice = perDeviceSpeedInfo;
@@ -134,29 +134,27 @@ private async Task<ApiData> GetMinerStatsDataAsyncPrivate(CancellationToken stop
134134
}
135135

136136
protected override void Init() { }
137-
private (IEnumerable<string> uuids, IEnumerable<int> ids) GetUUIDsAndIDs(IEnumerable<MiningPair> pairs)
137+
private (IEnumerable<int> excavatorids, IEnumerable<int> ids) GetUUIDsAndIDs(IEnumerable<MiningPair> pairs)
138138
{
139139
var devices = pairs
140-
.Select(p => p.Device)
141-
.Where(dev => dev is IGpuDevice);
140+
.Select(p => p.Device);
142141
if (devices.Any())
143142
{
144-
var devs = devices.Cast<IGpuDevice>();
145-
var uuids = devs.Select(gpu => _mappedDeviceIds[gpu.UUID]);
146-
var ids = devs.Select(gpu => gpu.PCIeBusID);
147-
return (uuids, ids);
143+
var excavatorIds = devices.Select(dev => _mappedDeviceIds[dev.UUID]);
144+
var ids = devices.Select(dev => dev.ID);
145+
return (excavatorIds, ids);
148146
}
149-
return (Enumerable.Empty<string>(), Enumerable.Empty<int>());
147+
return (Enumerable.Empty<int>(), Enumerable.Empty<int>());
150148
}
151149

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

src/Miners/Excavator/ExcavatorPlugin.PluginSupportedAlgorithms.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ public partial class ExcavatorPlugin
3333
new SAS(AlgorithmType.KAWPOW) { Enabled = false },
3434
new SAS(AlgorithmType.NeoScrypt),
3535
}
36+
},
37+
{
38+
DeviceType.CPU,
39+
new List<SAS>
40+
{
41+
new SAS(AlgorithmType.RandomXmonero)
42+
}
3643
}
3744
},
3845
AlgorithmNames = new Dictionary<AlgorithmType, string>
@@ -41,7 +48,8 @@ public partial class ExcavatorPlugin
4148
{ AlgorithmType.EtcHash, "etchash" },
4249
{ AlgorithmType.Autolykos, "autolykos" },
4350
{ AlgorithmType.KAWPOW, "kawpow" },
44-
{ AlgorithmType.NeoScrypt, "neoscrypt" }
51+
{ AlgorithmType.NeoScrypt, "neoscrypt" },
52+
{ AlgorithmType.RandomXmonero, "randomx" }
4553
}
4654
};
4755
}

0 commit comments

Comments
 (0)