Использование Java Stream вместо цикла for пропускает выполнение кода

Переключение набора циклического кода для использования параллельного потока, по-видимому, приводит к игнорированию определенной части кода.

Я использую MOA и Weka с Java 11 для запуска простого примера механизма рекомендаций, используя подсказки из исходного кода moa.tasks.EvaluateOnlineRecomender, который использует внутреннюю настройку задачи MOA для проверки точности реализации смещенной регуляризованной пошаговой одновременной матричной факторизации (BRISMF), предоставленной MOA. Вместо использования подготовленных MOA MovielensDataset класс, я перешел на Weka's Instances о перспективах применения инструментов Weka's ML.

Время обработки около миллиона экземпляров (я использую набор данных Movielens 1M) составило около 13-14 минут. В попытке увидеть улучшения, я хотел запустить его в параллельном потоке и стал подозрительным, когда задача завершилась примерно через 40 секунд. я нашел это BRISMFPredictor.predictRating всегда производил 0 в теле параллельного потока. Вот код для любого случая:

Код для инициализации:

import com.github.javacliparser.FileOption;
import com.github.javacliparser.IntOption;

import moa.options.ClassOption;
import moa.recommender.predictor.BRISMFPredictor;
import moa.recommender.predictor.RatingPredictor;
import moa.recommender.rc.data.RecommenderData;
import weka.core.converters.CSVLoader;

...

private static ClassOption datasetOption;
private static ClassOption ratingPredictorOption;
private static IntOption sampleFrequencyOption;
private static FileOption defaultFileOption;

static {
    ratingPredictorOption = new ClassOption("ratingPredictor",
            's', "Rating Predictor to evaluate on.", RatingPredictor.class,
            "moa.recommender.predictor.BRISMFPredictor");
    sampleFrequencyOption = new IntOption("sampleFrequency",
            'f', "How many instances between samples of the learning performance.", 100, 0, 2147483647);
    defaultFileOption = new FileOption("file",
            'f', "File to load.",
            "C:\\Users\\shiva\\Documents\\Java-ML\\mlapp\\data\\ml-1m\\ratings.dat", "dat", false);
}

... и внутри main() (Причуды с Века CSVLoader требуется, чтобы я заменил по умолчанию :: разделитель с +)

    var csvLoader = new CSVLoader();
    csvLoader.setSource(defaultFileOption.getFile());
    csvLoader.setFieldSeparator("+");
    var dataset = csvLoader.getDataSet();
    System.out.println(dataset.toSummaryString());

    var predictor = new BRISMFPredictor();
    predictor.prepareForUse();

    RecommenderData data = predictor.getData();
    data.clear();
    data.disableUpdates(false);

Теперь чередуем следующие фрагменты:

for (var instance : dataset) {
    var user = (int) instance.value(0);
    var item = (int) instance.value(1);
    var rating = instance.value(2);

    double predictedRating = predictor.predictRating(user, item);

    System.out.printf("User %d | Movie %d | Actual Rating %d | Predicted Rating %f%n",
                    user, item, Math.round(rating), predictedRating);
}

(Теперь, будучи новичком во всем, одновременно):

dataset.parallelStream().forEach(instance -> {
    var user = (int) instance.value(0);
    var item = (int) instance.value(1);
    var rating = instance.value(2);

    double predictedRating = predictor.predictRating(user, item);

    System.out.printf("User %d | Movie %d | Actual Rating %d | Predicted Rating %f%n",
                    user, item, Math.round(rating), predictedRating);
});

Теперь я решаю, что, черт возьми, эта операция не может быть выполнена параллельно, и я переключаю ее на использование stream(), Даже в этом случае сегмент, по-видимому, полностью игнорируется, поскольку выход снова равен 0.0 каждый раз

dataset.stream().forEach(instance -> {
    var user = (int) instance.value(0);
    var item = (int) instance.value(1);
    var rating = instance.value(2);

    double predictedRating = predictor.predictRating(user, item);

    System.out.printf("User %d | Movie %d | Actual Rating %d | Predicted Rating %f%n",
                    user, item, Math.round(rating), predictedRating);
});

Я пытался удалить оператор печати из прогона, но безрезультатно.

Очевидно, что я получаю ожидаемые выходные строки, состоящие из фактического и прогнозируемого рейтинга в течение примерно 13 минут в первом случае, но обнаруживаю, что прогнозируемый рейтинг равен 0,0 во втором случае с подозрительно низким временем выполнения. Есть что-то, по чему я упускаю?

РЕДАКТИРОВАТЬ: используя dataset.forEach() делает то же самое. Возможно, причуды лямбд?

0 ответов

Другие вопросы по тегам