最近我一直在努力解决多线程问题。我有一个训练神经网络的C#控制台应用程序。我通过任务为每个要训练的网络生成线程。我为我的上级课程所预订的教练课程创建了状态更新事件。在该事件处理程序中,我使用该模型的新状态更新状态数组。该阵列访问是我看到“死锁”类型行为的地方。我知道这不是死锁的规范定义,但是我想不出更好的术语来描述这种情况。下面是我的代码。我已经尽力了。
感谢您的帮助。谢谢
父代码
public class TrainingEngine
{
public enum UpdateStatus
{
Untrimmed = 0,
Trimmed,
Completed
}
private class TrainingStatus
{
public int Epoch { get; set; }
public UpdateStatus UpdateStatus { get; set; }
}
private static readonly object printLock = new object();
private ConcurrentDictionary<int, TrainingStatus> trainingStatus;
...other stuff...
private void UpdateEpochCompleted(TrainingStatus newStatus)
{
trainingStatus[newStatus.ThreadId] = newStatus;
PrintUpdate($"Model {newStatus.ThreadId + 1} completed epoch {newStatus.Epoch}.");
}
private void PrintUpdate(string trigger)
{
lock (printLock)
{
logger.Info(""); /***** DEADLOCKS HERE *****/
logger.Info($" {trigger}");
foreach (TrainingStatus status in trainingStatus.Values)
{
if (status.Status == TrainingStatus.UpdateStatus.Completed)
{
logger.Info(
$" {status.Status.ToString()} model {status.ThreadId + 1}",
100);
}
else
{
logger.Info(
$" {status.Status.ToString()} model {status.ThreadId + 1} working on epoch {status.Epoch} / {epochCount}",
100);
}
}
}
}
}
工人定义
public class NetworkTrainer
{
IProgress<TrainingStatus> UpdateCompleted { get; set; }
private double TrainNetwork(ActivationNetwork network,
int epochCount,
int geneCount,
double[][] inputData,
double[][] outputData,
int threadId,
bool trimmedModel)
{
for (int idxEpoch = 0; idxEpoch < epochCount; ++idxEpoch)
{
error += teacher.RunEpoch(inputData,
outputData);
UpdateCompleted?.Report(new TrainingStatus
{
Epoch = idxEpoch,
Status = (trimmedModel) ? TrainingStatus.UpdateStatus.Trimmed : TrainingStatus.UpdateStatus.Untrimmed,
ThreadId = threadId,
});
}
return error;
}
}
答案 0 :(得分:1)
我发现了问题。首先,我要感谢所有帮助过我的人,特别是Panagiotis Kanavos和usr。最初,我有一个写得不好的锁声明,很容易被重入。查看我的代码,我看不到这种情况如何发生。毕竟,每次训练大约需要30分钟。经过一番调查,我了解到,当我单击终端窗口并在窗口上留下一个白色正方形(标记)时,我已锁定访问终端。这意味着我的线程不再能够写入终端。我造成了僵局。有时,在笔记本电脑训练模型时,我会在笔记本电脑上做其他事情,然后单击终端以查看当前状态。
tl;博士如果单击终端,请按Enter键将其释放回系统。