ML.NET - 多线程时崩溃
ML.NET - crashing when multithreaded
我使用 ml.net 模型生成器制作了一个简单的图像识别程序,但是当我使用多线程同时检查多个文件夹中的图像时,它崩溃了。它 returns“在 Test.exe 中的 0x00007FFAB191F155 (tensorflow.dll) 抛出异常:0xC0000005:访问冲突读取位置 0x0000000002020202。”
代码就是ml.net模型生成器自动生成的代码:
public class ModelInput {
[ColumnName("Label"), LoadColumn(0)]
public string Label { get; set; }
[ColumnName("ImageSource"), LoadColumn(1)]
public string ImageSource { get; set; }
}
public class ModelOutput {
// ColumnName attribute is used to change the column name from
// its default value, which is the name of the field.
[ColumnName("PredictedLabel")]
public String Prediction { get; set; }
public float[] Score { get; set; }
}
class ConsumeModel {
private static Lazy<PredictionEngine<ModelInput, ModelOutput>> PredictionEngine = new Lazy<PredictionEngine<ModelInput, ModelOutput>>(CreatePredictionEngine);
public static string MLNetModelPath = Path.GetFullPath("MLModel.zip");
public static ModelOutput Predict(ModelInput input) {
ModelOutput result = PredictionEngine.Value.Predict(input);
return result;
}
public static PredictionEngine<ModelInput, ModelOutput> CreatePredictionEngine() {
// Create new MLContext
MLContext mlContext = new MLContext();
// Load model & create prediction engine
ITransformer mlModel = mlContext.Model.Load(MLNetModelPath, out var modelInputSchema);
var predEngine = mlContext.Model.CreatePredictionEngine<ModelInput, ModelOutput>(mlModel);
return predEngine;
}
}
我用来确定图像标签和多线程机制的代码如下:
public static void determine(string Dictpath) {
for (int j = 0; j < 9; j++) {
ModelInput sampleData = new ModelInput() {
ImageSource = Directory.GetFiles(Dictpath)[j],
};
var predictionResult = ConsumeModel.Predict(sampleData);
Console.WriteLine(predictionResult.Prediction);
}
}
为了多线程应用程序,我正在使用:
string[] Directories = Directory.GetDirectories("Saved/");
for (int i = 0; i < 10; i++) {
Task.Run(() => {
determine(Directories[i]);
});
}
我尝试减慢启动每个线程所需的时间,但我仍然得到相同的结果。它似乎只在单线程时有效,而在多线程时崩溃。
您正在同时使用来自多个线程的同一个 PredictionEngine
实例,没有同步。这仅在 PredictionEngine
class 为 thread-safe 时才可行。除非文档明确指出 “class 的所有 public 和受保护成员都是安全的并且可以从多个线程并发使用”,否则您应该假设class 不是 thread-safe,也不要这样使用。否则你会得到未定义的行为。您可以使用 lock
或其他方式同步对单个实例的所有访问,或者为每个线程创建一个专用实例。
我使用 ml.net 模型生成器制作了一个简单的图像识别程序,但是当我使用多线程同时检查多个文件夹中的图像时,它崩溃了。它 returns“在 Test.exe 中的 0x00007FFAB191F155 (tensorflow.dll) 抛出异常:0xC0000005:访问冲突读取位置 0x0000000002020202。”
代码就是ml.net模型生成器自动生成的代码:
public class ModelInput {
[ColumnName("Label"), LoadColumn(0)]
public string Label { get; set; }
[ColumnName("ImageSource"), LoadColumn(1)]
public string ImageSource { get; set; }
}
public class ModelOutput {
// ColumnName attribute is used to change the column name from
// its default value, which is the name of the field.
[ColumnName("PredictedLabel")]
public String Prediction { get; set; }
public float[] Score { get; set; }
}
class ConsumeModel {
private static Lazy<PredictionEngine<ModelInput, ModelOutput>> PredictionEngine = new Lazy<PredictionEngine<ModelInput, ModelOutput>>(CreatePredictionEngine);
public static string MLNetModelPath = Path.GetFullPath("MLModel.zip");
public static ModelOutput Predict(ModelInput input) {
ModelOutput result = PredictionEngine.Value.Predict(input);
return result;
}
public static PredictionEngine<ModelInput, ModelOutput> CreatePredictionEngine() {
// Create new MLContext
MLContext mlContext = new MLContext();
// Load model & create prediction engine
ITransformer mlModel = mlContext.Model.Load(MLNetModelPath, out var modelInputSchema);
var predEngine = mlContext.Model.CreatePredictionEngine<ModelInput, ModelOutput>(mlModel);
return predEngine;
}
}
我用来确定图像标签和多线程机制的代码如下:
public static void determine(string Dictpath) {
for (int j = 0; j < 9; j++) {
ModelInput sampleData = new ModelInput() {
ImageSource = Directory.GetFiles(Dictpath)[j],
};
var predictionResult = ConsumeModel.Predict(sampleData);
Console.WriteLine(predictionResult.Prediction);
}
}
为了多线程应用程序,我正在使用:
string[] Directories = Directory.GetDirectories("Saved/");
for (int i = 0; i < 10; i++) {
Task.Run(() => {
determine(Directories[i]);
});
}
我尝试减慢启动每个线程所需的时间,但我仍然得到相同的结果。它似乎只在单线程时有效,而在多线程时崩溃。
您正在同时使用来自多个线程的同一个 PredictionEngine
实例,没有同步。这仅在 PredictionEngine
class 为 thread-safe 时才可行。除非文档明确指出 “class 的所有 public 和受保护成员都是安全的并且可以从多个线程并发使用”,否则您应该假设class 不是 thread-safe,也不要这样使用。否则你会得到未定义的行为。您可以使用 lock
或其他方式同步对单个实例的所有访问,或者为每个线程创建一个专用实例。