public static bool ExtractPackage(this IKernel kernel) { try { string kernelDir = GetKernelDirFullName(kernel); if (string.IsNullOrEmpty(kernelDir)) { return(false); } if (!Directory.Exists(kernelDir)) { Directory.CreateDirectory(kernelDir); } string packageZipFileFullName = GetPackageFileFullName(kernel); if (string.IsNullOrEmpty(packageZipFileFullName)) { return(false); } if (!File.Exists(packageZipFileFullName)) { NTMinerConsole.DevDebug(() => $"试图解压的{packageZipFileFullName}文件不存在"); return(false); } ZipUtil.DecompressZipFile(packageZipFileFullName, kernelDir); return(true); } catch (Exception e) { Logger.ErrorDebugLine(e); return(false); } }
/// <summary> /// 注意:Request时原始HttpContent,Fire忽略Response /// </summary> /// <param name="host"></param> /// <param name="port"></param> /// <param name="controller"></param> /// <param name="action"></param> /// <param name="query"></param> /// <param name="content"></param> /// <param name="callback"></param> /// <param name="timeountMilliseconds"></param> public void FirePostAsync( string host, int port, string controller, string action, Dictionary <string, string> query, HttpContent content, Action callback = null, int timeountMilliseconds = 0) { Task.Factory.StartNew(() => { try { using (HttpClient client = RpcRoot.CreateHttpClient()) { if (timeountMilliseconds > 0) { client.SetTimeout(timeountMilliseconds); } Task <HttpResponseMessage> getHttpResponse = client.PostAsync(RpcRoot.GetUrl(host, port, controller, action, query), content); if (!getHttpResponse.Result.IsSuccessStatusCode) { NTMinerConsole.DevDebug($"{action} http response {getHttpResponse.Result.StatusCode.ToString()} {getHttpResponse.Result.ReasonPhrase}"); } callback?.Invoke(); } } catch { callback?.Invoke(); } }); }
public void RemoveMessagePath(IMessagePathId messagePathId) { lock (_locker) { var item = _messagePaths.FirstOrDefault(a => ReferenceEquals(a, messagePathId)); if (item != null) { _messagePaths.Remove(item); NTMinerConsole.DevDebug(() => "拆除路径" + messagePathId.Path + messagePathId.Description); } } }
private void PullSpeedInit() { if (_isPullSpeedInited) { return; } _isPullSpeedInited = true; Task.Factory.StartNew(() => { while (true) { DateTime now = DateTime.Now; if (_getSpeedOn.AddSeconds(10) <= now) { NTMinerConsole.DevDebug("周期拉取数据更新拍照源数据"); ClientData[] clientDatas = _dicByObjectId.Values.ToArray(); Task[] tasks = clientDatas.Select(CreatePullTask).ToArray(); Task.WaitAll(tasks, 5 * 1000); _getSpeedOn = now; #region 将NoSpeedSeconds秒内更新过的记录持久化到磁盘 List <MinerData> minerDatas = new List <MinerData>(); DateTime time = now.AddSeconds(-20); foreach (var clientData in _dicByObjectId.Values) { if (clientData.MinerActiveOn > time) { minerDatas.Add(MinerData.Create(clientData)); } else { clientData.IsMining = false; clientData.MainCoinSpeed = 0; clientData.DualCoinSpeed = 0; foreach (var item in clientData.GpuTable) { item.MainCoinSpeed = 0; item.DualCoinSpeed = 0; } } } if (minerDatas.Count > 0) { DoUpdateSave(minerDatas); } #endregion } else { System.Threading.Thread.Sleep((int)(_getSpeedOn.AddSeconds(10) - now).TotalMilliseconds); } } }, TaskCreationOptions.LongRunning); }
private void PullSpeedInit() { if (_isPullSpeedInited) { return; } _isPullSpeedInited = true; VirtualRoot.BuildEventPath <Per10SecondEvent>("周期拉取矿机状态", LogEnum.DevConsole, this.GetType(), PathPriority.Normal, message => { if (RpcRoot.IsOuterNet) { return; } Task.Factory.StartNew(() => { NTMinerConsole.DevDebug("周期拉取数据更新拍照源数据"); ClientData[] clientDatas = _dicByObjectId.Values.ToArray(); Task[] tasks = clientDatas.Select(CreatePullTask).ToArray(); Task.WaitAll(tasks, 5 * 1000); if (RpcRoot.IsOuterNet) { return; } #region 将NoSpeedSeconds秒内更新过的记录持久化到磁盘 List <MinerData> minerDatas = new List <MinerData>(); DateTime time = message.BornOn.AddSeconds(-20); foreach (var clientData in _dicByObjectId.Values) { if (clientData.MinerActiveOn > time) { minerDatas.Add(MinerData.Create(clientData)); } else { clientData.IsMining = false; clientData.MainCoinSpeed = 0; clientData.DualCoinSpeed = 0; foreach (var item in clientData.GpuTable) { item.MainCoinSpeed = 0; item.DualCoinSpeed = 0; } } } if (minerDatas.Count > 0) { DoUpdateSave(minerDatas); } #endregion }); }); }
/// <summary> /// 不会抛出异常,因为吞掉了异常 /// </summary> public static void Kill(int pid, bool waitForExit = false) { try { if (pid <= 0) { return; } string args = $"/F /T /PID {pid.ToString()}"; Cmd.RunClose("taskkill", args, waitForExit); NTMinerConsole.DevDebug(args); } catch { } }
/// <summary> /// 不会抛出异常,因为吞掉了异常 /// </summary> public static void KillOtherProcess(Process process, bool waitForExit = false) { if (process == null) { return; } try { string args = $"/F /FI \"pid ne {process.Id.ToString()}\" /T /IM {process.ProcessName}.exe"; Cmd.RunClose("taskkill", args, waitForExit); NTMinerConsole.DevDebug(args); } catch { } }
/// <summary> /// 不会抛出异常,因为吞掉了异常 /// </summary> public static void Kill(string processName, bool waitForExit = false) { try { if (string.IsNullOrEmpty(processName)) { return; } if (!processName.EndsWith(".exe")) { processName += ".exe"; } string args = $"/F /T /IM {processName}"; Cmd.RunClose("taskkill", args, waitForExit); NTMinerConsole.DevDebug(args); } catch { } }
public OverClockRange GetClockRange(int gpuIndex) { OverClockRange result = new OverClockRange(gpuIndex); try { if (!TryGetAtiGpu(gpuIndex, out ATIGPU gpuInfo)) { return(result); } GetTempLimitAndPowerLimit(gpuIndex, out int powerLimit, out int tempLimit); GetClockAndVolt(gpuIndex, out int memoryClock, out int memoryiVddc, out int coreClock, out int coreiVddc); result.PowerCurr = powerLimit; result.TempCurr = tempLimit; result.MemoryClockDelta = memoryClock; result.MemoryVoltage = memoryiVddc; result.CoreClockDelta = coreClock; result.CoreVoltage = coreiVddc; result.CoreClockMin = gpuInfo.CoreClockMin; result.CoreClockMax = gpuInfo.CoreClockMax; result.MemoryClockMin = gpuInfo.MemoryClockMin; result.MemoryClockMax = gpuInfo.MemoryClockMax; result.PowerMin = gpuInfo.PowerMin; result.PowerMax = gpuInfo.PowerMax; result.PowerDefault = gpuInfo.PowerDefault; result.TempLimitMin = gpuInfo.TempLimitMin; result.TempLimitMax = gpuInfo.TempLimitMax; result.TempLimitDefault = gpuInfo.TempLimitDefault; result.VoltMin = gpuInfo.VoltMin; result.VoltMax = gpuInfo.VoltMax; result.VoltDefault = gpuInfo.VoltDefault; result.FanSpeedMin = gpuInfo.FanSpeedMin; result.FanSpeedMax = gpuInfo.FanSpeedMax; #if DEBUG NTMinerConsole.DevDebug(() => $"GetClockRange {result.ToString()}"); #endif } catch (Exception e) { Logger.ErrorDebugLine(e); } return(result); }
public bool Init() { try { var r = AdlNativeMethods.ADL_Main_Control_Create(1); if (r < AdlStatus.ADL_OK) { NTMinerConsole.DevError(() => $"ADL_Main_Control_Create {r.ToString()}"); } if (r >= AdlStatus.ADL_OK) { int numberOfAdapters = 0; r = AdlNativeMethods.ADL_Adapter_NumberOfAdapters_Get(ref numberOfAdapters); if (r < AdlStatus.ADL_OK) { NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL_Adapter_NumberOfAdapters_Get)} {r.ToString()}"); } if (numberOfAdapters > 0) { ADLAdapterInfo[] adapterInfo = new ADLAdapterInfo[numberOfAdapters]; if (AdlNativeMethods.ADL_Adapter_AdapterInfo_Get(adapterInfo) >= AdlStatus.ADL_OK) { for (int i = 0; i < numberOfAdapters; i++) { NTMinerConsole.DevDebug(() => adapterInfo[i].ToString()); if (!string.IsNullOrEmpty(adapterInfo[i].UDID) && adapterInfo[i].VendorID == AdlConst.ATI_VENDOR_ID) { bool found = false; foreach (ATIGPU gpu in _gpuNames) { if (gpu.BusNumber == adapterInfo[i].BusNumber && gpu.DeviceNumber == adapterInfo[i].DeviceNumber) { found = true; break; } } if (!found) { _gpuNames.Add(new ATIGPU { AdapterName = adapterInfo[i].AdapterName.Trim(), AdapterIndex = adapterInfo[i].AdapterIndex, BusNumber = adapterInfo[i].BusNumber, DeviceNumber = adapterInfo[i].DeviceNumber }); } } } } } r = AdlNativeMethods.ADL2_Main_Control_Create(AdlNativeMethods.Main_Memory_Alloc, 1, ref context); if (r < AdlStatus.ADL_OK) { NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL2_Main_Control_Create)} {r.ToString()}"); } } _gpuNames = _gpuNames.OrderBy(a => a.BusNumber).ToList(); NTMinerConsole.DevDebug(() => string.Join(",", _gpuNames.Select(a => a.AdapterIndex))); } catch { return(false); } return(true); }
public ClientDataSet( IMinerDataRedis minerRedis, IClientActiveOnRedis clientActiveOnRedis, ISpeedDataRedis speedDataRedis, IMinerClientMqSender mqSender) : base(isPull: false, getDatas: callback => { var getMinersTask = minerRedis.GetAllAsync(); var getClientActiveOnsTask = clientActiveOnRedis.GetAllAsync(); var getSpeedsTask = speedDataRedis.GetAllAsync(); Task.WhenAll(getMinersTask, getClientActiveOnsTask, getSpeedsTask).ContinueWith(t => { NTMinerConsole.UserInfo($"从redis加载了 {getMinersTask.Result.Count} 条MinerData,和 {getSpeedsTask.Result.Count} 条SpeedData"); Dictionary <Guid, SpeedData> speedDataDic = getSpeedsTask.Result; Dictionary <string, DateTime> clientActiveOnDic = getClientActiveOnsTask.Result; List <ClientData> clientDatas = new List <ClientData>(); DateTime speedOn = DateTime.Now.AddMinutes(-3); foreach (var minerData in getMinersTask.Result) { var clientData = ClientData.Create(minerData); if (clientActiveOnDic.TryGetValue(minerData.Id, out DateTime activeOn)) { clientData.MinerActiveOn = activeOn; } clientDatas.Add(clientData); if (speedDataDic.TryGetValue(minerData.ClientId, out SpeedData speedData) && speedData.SpeedOn > speedOn) { clientData.Update(speedData, out bool _); } } callback?.Invoke(clientDatas); }); }) { _minerRedis = minerRedis; _clientActiveOnRedis = clientActiveOnRedis; _speedDataRedis = speedDataRedis; _mqSender = mqSender; VirtualRoot.BuildEventPath <Per100MinuteEvent>("周期将矿机的MinerActiveOn或NetActiveOn时间戳持久到redis", LogEnum.DevConsole, message => { var minerCients = _dicByObjectId.Values.ToArray(); DateTime time = message.BornOn.AddSeconds(-message.Seconds); int count = 0; foreach (var minerClient in minerCients) { // 如果活跃则更新到redis,否则就不更新了 DateTime activeOn = minerClient.GetActiveOn(); if (activeOn > time) { clientActiveOnRedis.SetAsync(minerClient.Id, activeOn); count++; } } NTMinerConsole.DevWarn($"{count.ToString()} 条活跃矿机的时间戳被持久化"); }, this.GetType()); // 上面的持久化时间戳到redis的目的主要是为了下面那个周期找出不活跃的矿机记录删除掉的逻辑能够在重启WebApiServer服务进程后不中断 VirtualRoot.BuildEventPath <Per2MinuteEvent>("周期找出用不活跃的矿机记录删除掉", LogEnum.DevConsole, message => { var clientDatas = _dicByObjectId.Values.ToArray(); Dictionary <string, List <ClientData> > dicByMACAddress = new Dictionary <string, List <ClientData> >(); DateTime minerClientExpireTime = message.BornOn.AddDays(-7); // 因为SpeedData尺寸较大,时效性较短,可以比CientData更早删除 DateTime minerSpeedExpireTime = message.BornOn.AddMinutes(-3); int count = 0; foreach (var clientData in clientDatas) { DateTime activeOn = clientData.GetActiveOn(); // 如果7天都没有活跃了 if (activeOn <= minerClientExpireTime) { RemoveByObjectId(clientData.Id); count++; } else if (activeOn <= minerSpeedExpireTime) { _speedDataRedis.DeleteByClientIdAsync(clientData.ClientId); } else if (!string.IsNullOrEmpty(clientData.MACAddress)) { if (!dicByMACAddress.TryGetValue(clientData.MACAddress, out List <ClientData> list)) { list = new List <ClientData>(); dicByMACAddress.Add(clientData.MACAddress, list); } list.Add(clientData); } } if (count > 0) { NTMinerConsole.DevWarn($"{count.ToString()} 条不活跃的矿机记录被删除"); } List <string> toRemoveIds = new List <string>(); foreach (var kv in dicByMACAddress) { if (kv.Value.Count > 1) { toRemoveIds.AddRange(kv.Value.Select(a => a.Id)); } } if (toRemoveIds.Count > 0) { count = 0; foreach (var id in toRemoveIds) { RemoveByObjectId(id); count++; } NTMinerConsole.DevWarn($"{count.ToString()} 条MAC地址重复的矿机记录被删除"); } NTMinerConsole.DevDebug($"QueryClients平均耗时 {AverageQueryClientsMilliseconds.ToString()} 毫秒"); }, this.GetType()); // 收到Mq消息之前一定已经初始化完成,因为Mq消费者在ClientSetInitedEvent事件之后才会创建 VirtualRoot.BuildEventPath <SpeedDatasMqEvent>("收到SpeedDatasMq消息后更新ClientData内存", LogEnum.None, path: message => { if (message.AppId == ServerRoot.HostConfig.ThisServerAddress) { return; } if (message.ClientIdIps == null || message.ClientIdIps.Length == 0) { return; } if (IsOldMqMessage(message.Timestamp)) { NTMinerConsole.UserOk(nameof(SpeedDatasMqEvent) + ":" + MqKeyword.SafeIgnoreMessage); return; } speedDataRedis.GetByClientIdsAsync(message.ClientIdIps.Select(a => a.ClientId).ToArray()).ContinueWith(t => { if (t.Result != null && t.Result.Length != 0) { foreach (var item in t.Result) { string minerIp = string.Empty; var clientIdIp = message.ClientIdIps.FirstOrDefault(a => a.ClientId == item.ClientId); if (clientIdIp != null) { minerIp = clientIdIp.MinerIp; } ReportSpeed(item.SpeedDto, minerIp, isFromWsServerNode: true); } } }); }, this.GetType()); VirtualRoot.BuildEventPath <MinerClientWsClosedMqEvent>("收到MinerClientWsClosedMq消息后更新NetActiveOn和IsOnline", LogEnum.None, path: message => { if (IsOldMqMessage(message.Timestamp)) { NTMinerConsole.UserOk(nameof(MinerClientWsClosedMqEvent) + ":" + MqKeyword.SafeIgnoreMessage); return; } if (_dicByClientId.TryGetValue(message.ClientId, out ClientData clientData)) { clientData.NetActiveOn = message.Timestamp; clientData.IsOnline = false; } }, this.GetType()); VirtualRoot.BuildEventPath <MinerClientsWsBreathedMqEvent>("收到MinerClientsWsBreathedMq消息后更新NetActiveOn", LogEnum.None, path: message => { if (IsOldMqMessage(message.Timestamp)) { NTMinerConsole.UserOk(nameof(MinerClientsWsBreathedMqEvent) + ":" + MqKeyword.SafeIgnoreMessage); return; } if (message.ClientIds != null && message.ClientIds.Length != 0) { foreach (var clientId in message.ClientIds) { if (_dicByClientId.TryGetValue(clientId, out ClientData clientData)) { clientData.NetActiveOn = message.Timestamp; clientData.IsOnline = true; } } } }, this.GetType()); VirtualRoot.BuildEventPath <MinerSignSetedMqEvent>("更新内存中的MinerData的MinerSign部分", LogEnum.None, path: message => { if (_dicByObjectId.TryGetValue(message.Data.Id, out ClientData clientData)) { clientData.Update(message.Data); } else { clientData = ClientData.Create(message.Data); Add(clientData); } clientData.NetActiveOn = DateTime.Now; clientData.IsOnline = true; clientData.IsOuterUserEnabled = true; }, this.GetType()); VirtualRoot.BuildCmdPath <QueryClientsForWsMqCommand>(path: message => { QueryClientsResponse response = AppRoot.QueryClientsForWs(message.Query); _mqSender.SendResponseClientsForWs(message.AppId, message.LoginName, message.SessionId, message.MqMessageId, response); }, this.GetType(), LogEnum.None); }
public void Route <TMessage>(TMessage message) where TMessage : IMessage { if (message == null) { throw new ArgumentNullException(nameof(message)); } MessagePath <TMessage>[] messagePaths = PathSetSet.GetMessagePathSet <TMessage>().GetMessagePaths(); if (messagePaths.Length == 0) { Type messageType = typeof(TMessage); MessageTypeAttribute messageTypeAttr = MessageTypeAttribute.GetMessageTypeAttribute(messageType); if (!messageTypeAttr.IsCanNoPath) { NTMinerConsole.DevWarn(() => messageType.FullName + "类型的消息没有对应的处理器"); } } else { foreach (var messagePath in messagePaths) { try { bool canGo = false; if (message is IEvent evt) { canGo = evt.TargetPathId == PathId.Empty || // 事件不是特定路径的事件则放行 messagePath.PathId == PathId.Empty || // 路径不是特定事件的路径则放行 evt.TargetPathId == messagePath.PathId; // 路径是特定事件的路径且路径和事件造型放行 } else if (message is ICmd cmd) { // 路径不是特定命令的路径则放行 if (messagePath.PathId == PathId.Empty) { canGo = true; } else { canGo = messagePath.PathId == cmd.MessageId; } } if (canGo && messagePath.ViaTimesLimit > 0) { // ViaTimesLimite小于0表示是不限定通过的次数的路径,不限定通过的次数的路径不需要消息每通过一次递减一次ViaTimesLimit计数 messagePath.DecreaseViaTimesLimit(onDownToZero: RemovePath); } if (!messagePath.IsEnabled) { continue; } if (canGo) { switch (messagePath.LogType) { case LogEnum.DevConsole: if (DevMode.IsDevMode) { NTMinerConsole.DevDebug(() => $"({typeof(TMessage).Name})->({messagePath.Location.Name}){messagePath.Description}"); } break; case LogEnum.UserConsole: NTMinerConsole.UserInfo($"({typeof(TMessage).Name})->({messagePath.Location.Name}){messagePath.Description}"); break; case LogEnum.Log: Logger.InfoDebugLine($"({typeof(TMessage).Name})->({messagePath.Location.Name}){messagePath.Description}"); break; case LogEnum.None: default: break; } messagePath.Go(message); } } catch (Exception e) { Logger.ErrorDebugLine(e); } } } }
public bool SetMemoryClock(int gpuIndex, int value, int voltage) { if (value < 0) { value = 0; } if (voltage < 0) { voltage = 0; } try { if (!TryGetAtiGpu(gpuIndex, out ATIGPU gpu)) { return(false); } bool isReset = value == 0 && voltage == 0; if (gpu.OverdriveVersion < 8) { ADLODNPerformanceLevelsX2 info = ADLODNPerformanceLevelsX2.Create(); var r = AdlNativeMethods.ADL2_OverdriveN_MemoryClocksX2_Get(_context, gpu.AdapterIndex, ref info); if (r < AdlStatus.ADL_OK) { NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL2_OverdriveN_MemoryClocksX2_Get)} {r.ToString()}"); return(false); } info.iMode = AdlConst.ODNControlType_Default; r = AdlNativeMethods.ADL2_OverdriveN_MemoryClocksX2_Set(_context, gpu.AdapterIndex, ref info); if (r < AdlStatus.ADL_OK) { NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL2_OverdriveN_MemoryClocksX2_Set)} {r.ToString()}"); return(false); } if (isReset) { return(true); } r = AdlNativeMethods.ADL2_OverdriveN_MemoryClocksX2_Get(_context, gpu.AdapterIndex, ref info); if (r < AdlStatus.ADL_OK) { NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL2_OverdriveN_MemoryClocksX2_Get)} {r.ToString()}"); return(false); } info.iMode = AdlConst.ODNControlType_Manual; int index = 0; for (int i = 0; i < info.aLevels.Length; i++) { if (info.aLevels[i].iEnabled != 0) { index = i; } } NTMinerConsole.DevDebug(() => $"{nameof(SetMemoryClock)} PState {index.ToString()} value={value.ToString()} voltage={voltage.ToString()}"); if (value != 0) { info.aLevels[index].iClock = value * 100; } if (voltage != 0) { info.aLevels[index].iVddc = voltage; } r = AdlNativeMethods.ADL2_OverdriveN_MemoryClocksX2_Set(_context, gpu.AdapterIndex, ref info); if (r < AdlStatus.ADL_OK) { NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL2_OverdriveN_MemoryClocksX2_Set)} {r.ToString()}"); return(false); } } else { if (GetOD8CurrentSetting(gpu.AdapterIndex, out ADLOD8CurrentSetting odCurrentSetting)) { SetOD8Range(gpu.ADLOD8InitSetting, odCurrentSetting, gpu.AdapterIndex, ADLOD8SettingId.OD8_UCLK_FMAX, isReset, value * 100); } } return(true); } catch (Exception e) { Logger.ErrorDebugLine(e); return(false); } }
private bool Init() { try { if (_isHasATIGpu) { foreach (var adapterInfo in _adapterInfoes) { NTMinerConsole.DevDebug(() => adapterInfo.ToString()); bool found = false; foreach (ATIGPU gpu in _gpuNames) { if (gpu.BusNumber == adapterInfo.BusNumber && gpu.DeviceNumber == adapterInfo.DeviceNumber) { found = true; break; } } if (!found) { int adapterIndex = adapterInfo.AdapterIndex; int overdriveVersion = 0; try { if (AdlNativeMethods.ADL_Overdrive_Caps(adapterIndex, out _, out _, out overdriveVersion) != AdlStatus.ADL_OK) { overdriveVersion = -1; } } catch (Exception ex) { Logger.ErrorDebugLine(ex); } ADLODNCapabilitiesX2 info = new ADLODNCapabilitiesX2(); try { var r = AdlNativeMethods.ADL2_OverdriveN_CapabilitiesX2_Get(_context, adapterIndex, ref info); if (r < AdlStatus.ADL_OK) { NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL2_OverdriveN_CapabilitiesX2_Get)} {r.ToString()}"); } } catch (Exception ex) { Logger.ErrorDebugLine(ex); } int maxLevels = info.iMaximumNumberOfPerformanceLevels; int fanSpeedMin = 0; int fanSpeedMax = 0; ADLFanSpeedInfo afsi = new ADLFanSpeedInfo(); try { var r = AdlNativeMethods.ADL_Overdrive5_FanSpeedInfo_Get(adapterIndex, 0, ref afsi); if (r < AdlStatus.ADL_OK) { NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL_Overdrive5_FanSpeedInfo_Get)} {r.ToString()}"); } else { fanSpeedMax = afsi.MaxPercent; fanSpeedMin = afsi.MinPercent; } } catch (Exception ex) { Logger.ErrorDebugLine(ex); } ADLODNPerformanceLevelsX2 systemClockX2 = ADLODNPerformanceLevelsX2.Create(); systemClockX2.iNumberOfPerformanceLevels = maxLevels; try { var r = AdlNativeMethods.ADL2_OverdriveN_SystemClocksX2_Get(_context, adapterIndex, ref systemClockX2); if (r < AdlStatus.ADL_OK) { NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL2_OverdriveN_SystemClocksX2_Get)} {r.ToString()}"); } } catch (Exception ex) { Logger.ErrorDebugLine(ex); } int gpuLevel = 0; int memoryLevel = 0; for (int j = 0; j < systemClockX2.aLevels.Length; j++) { if (systemClockX2.aLevels[j].iEnabled != 0) { gpuLevel = j + 1; } } ADLODNPerformanceLevelsX2 memoryClockX2 = ADLODNPerformanceLevelsX2.Create(); memoryClockX2.iNumberOfPerformanceLevels = maxLevels; try { var r = AdlNativeMethods.ADL2_OverdriveN_MemoryClocksX2_Get(_context, adapterIndex, ref memoryClockX2); if (r < AdlStatus.ADL_OK) { NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL2_OverdriveN_MemoryClocksX2_Get)} {r.ToString()}"); } } catch (Exception ex) { Logger.ErrorDebugLine(ex); } for (int j = 0; j < memoryClockX2.aLevels.Length; j++) { if (memoryClockX2.aLevels[j].iEnabled != 0) { memoryLevel = j + 1; } } int powerMin = info.power.iMin + 100; int powerMax = info.power.iMax + 100; int powerDefault = info.power.iDefault + 100; int voltMin = info.svddcRange.iMin; // 0 int voltMax = info.svddcRange.iMax; // 0 int voltDefault = info.svddcRange.iDefault; // 0 int tempLimitMin = info.powerTuneTemperature.iMin; int tempLimitMax = info.powerTuneTemperature.iMax; int tempLimitDefault = info.powerTuneTemperature.iDefault; int coreClockMin = info.sEngineClockRange.iMin * 10; int coreClockMax = info.sEngineClockRange.iMax * 10; int memoryClockMin = info.sMemoryClockRange.iMin * 10; int memoryClockMax = info.sMemoryClockRange.iMax * 10; bool apiSupported = gpuLevel > 0 && memoryLevel > 0; ADLOD8InitSetting odInitSetting = ADLOD8InitSetting.Create(); if (!apiSupported) { try { if (overdriveVersion == 8) { if (GetOD8InitSetting(adapterIndex, out odInitSetting)) { apiSupported = true; gpuLevel = 3; memoryLevel = 0; maxLevels = 3; powerMin = 0; powerMax = 0; powerDefault = 0; voltMin = 0; voltMax = 0; voltDefault = 0; tempLimitMin = 0; tempLimitMax = 0; tempLimitDefault = 0; coreClockMin = 0; coreClockMax = 0; memoryClockMin = 0; memoryClockMax = 0; if ((odInitSetting.overdrive8Capabilities & (int)ADLOD8FeatureControl.ADL_OD8_GFXCLK_LIMITS) == (int)ADLOD8FeatureControl.ADL_OD8_GFXCLK_LIMITS || (odInitSetting.overdrive8Capabilities & (int)ADLOD8FeatureControl.ADL_OD8_GFXCLK_CURVE) == (int)ADLOD8FeatureControl.ADL_OD8_GFXCLK_CURVE) { coreClockMin = odInitSetting.od8SettingTable[(int)ADLOD8SettingId.OD8_GFXCLK_FMAX].minValue * 1000; coreClockMax = odInitSetting.od8SettingTable[(int)ADLOD8SettingId.OD8_GFXCLK_FMAX].maxValue * 1000; voltMin = odInitSetting.od8SettingTable[(int)ADLOD8SettingId.OD8_GFXCLK_VOLTAGE3].minValue; voltMax = odInitSetting.od8SettingTable[(int)ADLOD8SettingId.OD8_GFXCLK_VOLTAGE3].maxValue; powerMin = 100 + odInitSetting.od8SettingTable[(int)ADLOD8SettingId.OD8_POWER_PERCENTAGE].minValue; powerMax = 100 + odInitSetting.od8SettingTable[(int)ADLOD8SettingId.OD8_POWER_PERCENTAGE].maxValue; memoryClockMin = odInitSetting.od8SettingTable[(int)ADLOD8SettingId.OD8_UCLK_FMAX].minValue * 1000; memoryClockMax = odInitSetting.od8SettingTable[(int)ADLOD8SettingId.OD8_UCLK_FMAX].maxValue * 1000; } #if DEBUG Logger.Debug(odInitSetting.ToString()); #endif } } } catch (Exception ex) { Logger.ErrorDebugLine(ex); } } if (fanSpeedMax <= 0) { fanSpeedMax = 100; } if (powerMax <= 0) { powerMax = 100; } _gpuNames.Add(new ATIGPU { AdapterName = adapterInfo.AdapterName.Trim(), AdapterIndex = adapterIndex, BusNumber = adapterInfo.BusNumber, DeviceNumber = adapterInfo.DeviceNumber, OverdriveVersion = overdriveVersion, MaxLevels = maxLevels, ApiSupported = apiSupported, GpuLevels = gpuLevel, MemoryLevels = memoryLevel, CoreClockMin = coreClockMin, CoreClockMax = coreClockMax, MemoryClockMin = memoryClockMin, MemoryClockMax = memoryClockMax, PowerMin = powerMin, PowerMax = powerMax, PowerDefault = powerDefault, TempLimitMin = tempLimitMin, TempLimitMax = tempLimitMax, TempLimitDefault = tempLimitDefault, VoltMin = voltMin, VoltMax = voltMax, VoltDefault = voltDefault, FanSpeedMax = fanSpeedMax, FanSpeedMin = fanSpeedMin, ADLOD8InitSetting = odInitSetting }); } } } _gpuNames = _gpuNames.OrderBy(a => a.BusNumber).ToList(); NTMinerConsole.DevDebug(() => string.Join(",", _gpuNames.Select(a => a.AdapterIndex))); } catch (Exception ex) { Logger.ErrorDebugLine(ex); return(false); } return(true); }
public void Init(INTMinerContext root) { if (_isInited) { return; } _isInited = true; VirtualRoot.BuildEventPath <GpuStateChangedEvent>("当显卡温度变更时守卫温度防线", LogEnum.None, path: message => { IGpu gpu = message.Source; if (gpu.Index == NTMinerContext.GpuAllId || root.MinerProfile.CoinId == Guid.Empty) { return; } IGpuProfile gpuProfile; if (NTMinerContext.Instance.GpuProfileSet.IsOverClockGpuAll(root.MinerProfile.CoinId)) { gpuProfile = NTMinerContext.Instance.GpuProfileSet.GetGpuProfile(root.MinerProfile.CoinId, NTMinerContext.GpuAllId); } else { gpuProfile = NTMinerContext.Instance.GpuProfileSet.GetGpuProfile(root.MinerProfile.CoinId, gpu.Index); } if (!gpuProfile.IsAutoFanSpeed) { return; } // 显卡温度抵达防御温度的时间 if (!_fightedOnDic.TryGetValue(gpu.Index, out DateTime fightedOn)) { fightedOn = DateTime.Now; _fightedOnDic.Add(gpu.Index, fightedOn); } if (gpu.FanSpeed == 100 && gpu.Temperature > _guardTemp) { NTMinerConsole.DevDebug(() => $"GPU{gpu.Index.ToString()} 温度{gpu.Temperature.ToString()}大于防线温度{_guardTemp.ToString()},但风扇转速已达100%"); } else if (gpu.Temperature < _guardTemp) { if (!_preTempDic.ContainsKey(gpu.Index)) { _preTempDic.Add(gpu.Index, 0); } // 如果当前温度比上次的温度大 if (gpu.Temperature > _preTempDic[gpu.Index]) { fightedOn = DateTime.Now; _fightedOnDic[gpu.Index] = fightedOn; } _preTempDic[gpu.Index] = gpu.Temperature; // 如果距离抵达防御温度的时间已经很久了则降速风扇 if (fightedOn.AddSeconds(_fanSpeedDownSeconds) < DateTime.Now) { int cool = (int)(gpu.FanSpeed - _fanSpeedDownStep); // 如果温度低于50度则直接将风扇设为驱动默认的最小转速 if (gpu.Temperature < 50) { cool = gpu.CoolMin; } if (cool >= gpu.CoolMin) { _fightedOnDic[gpu.Index] = DateTime.Now; root.GpuSet.OverClock.SetFanSpeed(gpu.Index, cool); NTMinerConsole.DevDebug(() => $"GPU{gpu.Index.ToString()} 风扇转速由{gpu.FanSpeed.ToString()}%调低至{cool.ToString()}%"); } } } else if (gpu.Temperature > _guardTemp) { uint cool; uint len; // 防线突破可能是由于小量降低风扇转速造成的 if (fightedOn.AddSeconds(_fanSpeedDownSeconds) < DateTime.Now) { _fightedOnDic[gpu.Index] = DateTime.Now; len = 100 - gpu.FanSpeed; } else { len = _fanSpeedDownStep; } cool = gpu.FanSpeed + (uint)Math.Ceiling(len / 2.0); if (cool > 100) { cool = 100; } if (cool <= 100) { root.GpuSet.OverClock.SetFanSpeed(gpu.Index, (int)cool); NTMinerConsole.DevDebug(() => $"GPU{gpu.Index.ToString()} 风扇转速由{gpu.FanSpeed.ToString()}%调高至{cool.ToString()}%"); } } }, location: this.GetType()); }
public bool SetMemoryClock(int gpuIndex, int value, int voltage) { if (value < 0) { value = 0; } if (voltage < 0) { voltage = 0; } try { if (!TryGpuAdapterIndex(gpuIndex, out int adapterIndex)) { return(false); } ADLODNPerformanceLevelsX2 info = ADLODNPerformanceLevelsX2.Create(); var r = AdlNativeMethods.ADL2_OverdriveN_MemoryClocksX2_Get(context, adapterIndex, ref info); if (r < AdlStatus.ADL_OK) { NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL2_OverdriveN_MemoryClocksX2_Get)} {r.ToString()}"); return(false); } info.iMode = AdlConst.ODNControlType_Default; r = AdlNativeMethods.ADL2_OverdriveN_MemoryClocksX2_Set(context, adapterIndex, ref info); if (r < AdlStatus.ADL_OK) { NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL2_OverdriveN_MemoryClocksX2_Set)} {r.ToString()}"); return(false); } bool isReset = value == 0 && voltage == 0; if (isReset) { return(true); } r = AdlNativeMethods.ADL2_OverdriveN_MemoryClocksX2_Get(context, adapterIndex, ref info); if (r < AdlStatus.ADL_OK) { NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL2_OverdriveN_MemoryClocksX2_Get)} {r.ToString()}"); return(false); } info.iMode = AdlConst.ODNControlType_Manual; int index = 0; for (int i = 0; i < info.aLevels.Length; i++) { if (info.aLevels[i].iEnabled != 0) { index = i; } } NTMinerConsole.DevDebug(() => $"SetMemoryClock PState {index.ToString()} value={value.ToString()} voltage={voltage.ToString()}"); if (value != 0) { info.aLevels[index].iClock = value * 100; } if (voltage != 0) { info.aLevels[index].iVddc = voltage; } r = AdlNativeMethods.ADL2_OverdriveN_MemoryClocksX2_Set(context, adapterIndex, ref info); if (r < AdlStatus.ADL_OK) { NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL2_OverdriveN_MemoryClocksX2_Set)} {r.ToString()}"); return(false); } return(true); } catch (Exception e) { Logger.ErrorDebugLine(e); return(false); } }
public void Init(INTMinerContext root) { if (_isInited) { return; } _isInited = true; VirtualRoot.BuildEventPath <Per1SecondEvent>("周期性调节风扇转速守卫温度防线", LogEnum.None, path: message => { double ki = _ti > 0 ? _dt / _ti : _dt; double kd = _td / _dt; foreach (var gpu in root.GpuSet.AsEnumerable()) { if (gpu.Index == NTMinerContext.GpuAllId) { continue; } if (!_preDistanceToGuard1.ContainsKey(gpu.Index)) { _preDistanceToGuard1.Add(gpu.Index, 0); } if (!_preDistanceToGuard2.ContainsKey(gpu.Index)) { _preDistanceToGuard2.Add(gpu.Index, 0); } if (!_lastOutputCool.ContainsKey(gpu.Index)) { _lastOutputCool.Add(gpu.Index, 0); } IGpuProfile gpuProfile; if (NTMinerContext.Instance.GpuProfileSet.IsOverClockGpuAll(root.MinerProfile.CoinId)) { gpuProfile = NTMinerContext.Instance.GpuProfileSet.GetGpuProfile(root.MinerProfile.CoinId, NTMinerContext.GpuAllId); } else { gpuProfile = NTMinerContext.Instance.GpuProfileSet.GetGpuProfile(root.MinerProfile.CoinId, gpu.Index); } if ( !gpuProfile.IsAutoFanSpeed || !NTMinerContext.Instance.IsMining || !NTMinerContext.Instance.GpuProfileSet.IsOverClockEnabled(root.LockedMineContext.MainCoin.GetId()) ) { _lastOutputCool[gpu.Index] = gpuProfile.Cool; _preDistanceToGuard1[gpu.Index] = 0; _preDistanceToGuard2[gpu.Index] = 0; continue; } // 敌人距离防线的距离,越过防线为负 int distanceToGuard = _guardTemp - gpu.Temperature; double delta = _kp * (distanceToGuard - _preDistanceToGuard1[gpu.Index]) + ki * distanceToGuard + kd * (distanceToGuard - 2 * _preDistanceToGuard1[gpu.Index] + _preDistanceToGuard2[gpu.Index]); _preDistanceToGuard2[gpu.Index] = _preDistanceToGuard1[gpu.Index]; _preDistanceToGuard1[gpu.Index] = distanceToGuard; double output = _lastOutputCool[gpu.Index] - delta; if (output > 100) { NTMinerConsole.DevDebug(() => $"GPU{gpu.Index.ToString()} 温度{gpu.Temperature.ToString()}大于防线温度{_guardTemp.ToString()},但风扇转速已达100%"); } output = output > gpu.CoolMax ? gpu.CoolMax : output; output = output < gpu.CoolMin ? gpu.CoolMin : output; root.GpuSet.OverClock.SetFanSpeed(gpu.Index, (int)output); if (output - _lastOutputCool[gpu.Index] > _signinicant) { NTMinerConsole.DevDebug(() => $"GPU{gpu.Index.ToString()} 风扇转速由{_lastOutputCool[gpu.Index].ToString()}%调高至{output.ToString()}%"); } if (_lastOutputCool[gpu.Index] - output > _signinicant) { NTMinerConsole.DevDebug(() => $"GPU{gpu.Index.ToString()} 风扇转速由{_lastOutputCool[gpu.Index].ToString()}%调低至{output.ToString()}%"); } _lastOutputCool[gpu.Index] = output; } }, location: this.GetType()); }
public MinerProfileViewModel() { if (WpfUtil.IsInDesignMode) { return; } if (Instance != null) { throw new InvalidProgramException(); } if (this.IsCreateShortcut) { CreateShortcut(); } this.Up = new DelegateCommand <string>(propertyName => { WpfUtil.Up(this, propertyName); }); this.Down = new DelegateCommand <string>(propertyName => { WpfUtil.Down(this, propertyName); }); this.WsRetry = new DelegateCommand(() => { RpcRoot.Client.NTMinerDaemonService.StartOrStopWsAsync(isResetFailCount: true); IsConnecting = true; }); if (ClientAppType.IsMinerClient) { VirtualRoot.AddCmdPath <SetAutoStartCommand>(message => { this.IsAutoStart = message.IsAutoStart; this.IsAutoBoot = message.IsAutoBoot; }, this.GetType(), LogEnum.None); VirtualRoot.AddEventPath <StartingMineFailedEvent>("开始挖矿失败", LogEnum.DevConsole, action: message => { IsMining = false; NTMinerConsole.UserError(message.Message); }, location: this.GetType()); // 群控客户端已经有一个执行RefreshWsStateCommand命令的路径了 VirtualRoot.AddCmdPath <RefreshWsStateCommand>(message => { #region if (message.WsClientState != null) { this.IsWsOnline = message.WsClientState.Status == WsClientStatus.Open; if (message.WsClientState.ToOut) { VirtualRoot.Out.ShowWarn(message.WsClientState.Description, autoHideSeconds: 3); } if (!message.WsClientState.ToOut || !this.IsWsOnline) { this.WsDescription = message.WsClientState.Description; } if (!this.IsWsOnline) { if (message.WsClientState.LastTryOn != DateTime.MinValue) { this.WsLastTryOn = message.WsClientState.LastTryOn; } if (message.WsClientState.NextTrySecondsDelay > 0) { WsNextTrySecondsDelay = message.WsClientState.NextTrySecondsDelay; } } } #endregion }, this.GetType(), LogEnum.DevConsole); VirtualRoot.AddEventPath <Per1SecondEvent>("外网群控重试秒表倒计时", LogEnum.None, action: message => { if (IsOuterUserEnabled && !IsWsOnline) { if (WsNextTrySecondsDelay > 0) { WsNextTrySecondsDelay--; } else if (WsLastTryOn == DateTime.MinValue) { this.RefreshWsDaemonState(); } OnPropertyChanged(nameof(WsLastTryOnText)); } }, this.GetType()); VirtualRoot.AddEventPath <WsServerOkEvent>("服务器Ws服务已可用", LogEnum.DevConsole, action: message => { if (IsOuterUserEnabled && !IsWsOnline) { StartOrStopWs(); } }, this.GetType()); } NTMinerContext.SetRefreshArgsAssembly((reason) => { NTMinerConsole.DevDebug(() => $"RefreshArgsAssembly" + reason, ConsoleColor.Cyan); #region 确保双挖权重在合法的范围内 if (CoinVm != null && CoinVm.CoinKernel != null && CoinVm.CoinKernel.Kernel != null) { var coinKernelProfile = CoinVm.CoinKernel.CoinKernelProfile; var kernelInput = CoinVm.CoinKernel.Kernel.KernelInputVm; if (coinKernelProfile != null && kernelInput != null) { if (coinKernelProfile.IsDualCoinEnabled && !kernelInput.IsAutoDualWeight) { if (coinKernelProfile.DualCoinWeight > kernelInput.DualWeightMax) { coinKernelProfile.DualCoinWeight = kernelInput.DualWeightMax; } else if (coinKernelProfile.DualCoinWeight < kernelInput.DualWeightMin) { coinKernelProfile.DualCoinWeight = kernelInput.DualWeightMin; } NTMinerContext.Instance.MinerProfile.SetCoinKernelProfileProperty(coinKernelProfile.CoinKernelId, nameof(coinKernelProfile.DualCoinWeight), coinKernelProfile.DualCoinWeight); } } } #endregion NTMinerContext.Instance.CurrentMineContext = NTMinerContext.Instance.CreateMineContext(); if (NTMinerContext.Instance.CurrentMineContext != null) { this.ArgsAssembly = NTMinerContext.Instance.CurrentMineContext.CommandLine; } else { this.ArgsAssembly = string.Empty; } }); AppRoot.AddCmdPath <RefreshAutoBootStartCommand>("刷新开机启动和自动挖矿的展示", LogEnum.DevConsole, action: message => { this.OnPropertyChanged(nameof(IsAutoBoot)); this.OnPropertyChanged(nameof(IsAutoStart)); }, location: this.GetType()); AppRoot.AddEventPath <MinerProfilePropertyChangedEvent>("MinerProfile设置变更后刷新VM内存", LogEnum.DevConsole, action: message => { OnPropertyChanged(message.PropertyName); }, location: this.GetType()); VirtualRoot.AddEventPath <LocalContextReInitedEventHandledEvent>("本地上下文视图模型集刷新后刷新界面", LogEnum.DevConsole, action: message => { AllPropertyChanged(); if (CoinVm != null) { CoinVm.OnPropertyChanged(nameof(CoinVm.Wallets)); CoinVm.CoinKernel?.CoinKernelProfile.SelectedDualCoin?.OnPropertyChanged(nameof(CoinVm.Wallets)); CoinVm.CoinProfile?.OnPropertyChanged(nameof(CoinVm.CoinProfile.SelectedWallet)); CoinVm.CoinKernel?.CoinKernelProfile.SelectedDualCoin?.CoinProfile?.OnPropertyChanged(nameof(CoinVm.CoinProfile.SelectedDualCoinWallet)); } }, location: this.GetType()); VirtualRoot.AddEventPath <CoinVmAddedEvent>("Vm集添加了新币种后刷新MinerProfileVm内存", LogEnum.DevConsole, action: message => { OnPropertyChanged(nameof(CoinVm)); }, this.GetType()); VirtualRoot.AddEventPath <CoinVmRemovedEvent>("Vm集删除了新币种后刷新MinerProfileVm内存", LogEnum.DevConsole, action: message => { OnPropertyChanged(nameof(CoinVm)); }, this.GetType()); }
public void InfoDebugLine(object message) { NTMinerConsole.DevDebug(message?.ToString()); _log.Info(message); }