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 或其他方式同步对单个实例的所有访问,或者为每个线程创建一个专用实例。