Дополнительные байты появляются при построении файловых данных с использованием нескольких потоков - PullRequest
2 голосов
/ 06 апреля 2011

Я работаю с крупномасштабным набором данных, и после построения модели я использую многопоточность (весь проект на Java) следующим образом:

OutputStream out = new BufferedOutputStream(new FileOutputStream(outFile));

int i=0;
Collection<Track1Callable> callables = new ArrayList<Track1Callable>();

// For each entry in the test file, do watever needs to be done.
// Track1Callable actually processes that entry and returns a double value.
for (Pair<PreferenceArray, long[]> tests : new DataFileIterable(
        KDDCupDataModel.getTestFile(dataFileDirectory))) {
    PreferenceArray userTest = tests.getFirst();
    callables.add(new Track1Callable(recommender, userTest));
    i++;
}

ExecutorService executor = Executors.newFixedThreadPool(cores); //24 cores
List<Future<byte[]>> results = executor.invokeAll(callables);
executor.shutdown();

for (Future<byte[]> result : results) {
    for (byte estimate : result.get()) {
        out.write(estimate);
    }
}
out.flush();
out.close();

Когда я получаю результат от каждого вызываемого объекта, выводим его в файл. Соответствует ли этот вывод точному порядку, как был составлен список исходных Callables? Несмотря на то, что некоторые заканчивают раньше других? Кажется, это должно быть, но не уверен.

Кроме того, я ожидаю, что в файл будет записано 6,2 миллиона байт. Но я получаю дополнительные 2000 байтов (да бесплатно). Это портит мое представление, и я думаю, что это из-за некоторых проблем параллелизма. Я проверил это на небольшом наборе данных, и, похоже, он отлично работает (ожидается и получено 264 байта).

Что-то не так, что я делаю с платформой Executor или Futures?

Ответы [ 2 ]

0 голосов
/ 06 апреля 2011

Порядок, в котором выполняются вызываемые объекты, не имеет значения из кода, который вы здесь имеете.Вы пишете результаты в том порядке, в котором вы храните фьючерсы в списке.Даже если они были выполнены в обратном порядке, файл должен выглядеть так же, как запись вашего файла однопоточная.

Я подозреваю, что ваши вызовы взаимодействуют друг с другом, и вы получите разные результаты в зависимости от количества ядер, которые вы используете.использовать.Например, вы можете использовать SimpleDateFormat.

Я предлагаю вам выполнить это дважды в одной и той же программе с набором данных, который завершается за короткое время.Сначала запустите его только с одним потоком в пуле потоков, а второй раз - с 24 потоками. Вы сможете сравнить результаты обоих запусков с Arrays.equals(byte[], byte[]) и убедиться, что вы получите абсолютно одинаковые результаты.

0 голосов
/ 06 апреля 2011

В: Порядок совпадает с тем, который указан для задач? Да .

Из API:

Возвращает: список фьючерсов представляя задачи, в том же последовательный порядок как произведено итератор для заданного списка задач. Если время операции не истекло, каждый задача будет выполнена. Если бы это было некоторые из этих задач не будут завершено.

Что касается «лишних» байтов: пытались ли вы делать все это в последовательном порядке (т.е. без использования исполнителя) и проверять, получаете ли вы другие результаты? Похоже, что ваша проблема находится за пределами предоставленного кода (и, вероятно, не из-за параллелизма).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...