2

私は大規模なデータセットに取り組んでおり、モデルを構築した後、次のようにマルチスレッド (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();

各 callable から結果を受け取ったら、それをファイルに出力します。これは、最初の Callables のリストが作成された順序どおりに出力されますか? 他の人より先に完了したにもかかわらず?するべきだと思われますが、確かではありません。

また、合計 620 万バイトが出力ファイルに書き込まれると予想しています。しかし、追加の 2000 バイトを取得します (無料です)。それは私の提出を台無しにします、そしてそれはいくつかの並行性の問題によるものだと思います。これを小さなデータセットでテストしたところ、問題なく動作しているようです (264 バイトが期待され、受信されました)。

Executor フレームワークまたは Futures で何か問題がありますか?

4

2 に答える 2

0

callable が実行される順序は、ここにあるコードからは重要ではありません。先物をリストに保存する順序で結果を書き込みます。それらが逆の順序で実行されたとしても、ファイルの書き込みがシングルスレッドであるため、ファイルは同じように見えるはずです。

あなたの呼び出し可能オブジェクトは互いに相互作用していると思われ、使用するコアの数に応じて異なる結果が得られます。たとえば、SimpleDateFormat を使用している可能性があります。

短時間で完了するデータセットを使用して、同じプログラムでこれを 2 回実行することをお勧めします。最初はスレッド プール内の 1 つのスレッドのみで実行し、2 回目は 24 のスレッドで実行します。両方の実行の結果を比較すると、Arrays.equals(byte[], byte[])まったく同じ結果が得られることがわかります。

于 2011-04-06T07:13:51.337 に答える
0

Q: 順番はタスクに指定されたものと同じですか? はい

API から:

戻り値: 指定されたタスク リストのイテレータによって生成されるのと同じ順序で、タスクを表す Future のリスト。操作がタイムアウトしなかった場合、各タスクは完了しています。タイムアウトした場合、これらのタスクの一部は完了していません。

「余分な」バイトについては、これらすべてを順番に (つまり、executor を使用せずに) 実行して、異なる結果が得られるかどうかを確認しましたか? あなたの問題は、提供されたコードの外にあるようです (そしておそらく同時実行性が原因ではありません)。

于 2011-04-06T00:31:59.047 に答える