3

1000それぞれ乱数に基づいて計算を行う必要があります。実行全体が再現可能である必要があります。

シングルスレッド環境では、シードに基づいてランダムを作成し、それを各計算に使用します。

Random random = new Random(37);
for (Calculation c : calculations) {
    c.doCalculation(r.nextInt());
}

私が10スレッドを持っているマルチスレッド環境では、シードされたランダムシードスレッドランダムがあります:

Random initRandom = new Random(37);
for (List<Calculation> p : calculationPartitions) {
    final Random threadRandom = new Random(initRandom.nextLong());
    executorService.submit(() -> {
        for (Calculation c : p) {
            c.doCalculation(threadRandom.nextInt());
        }
    });
}
// Merge the calculation results back in the same order as the calculationPartitions
...

これは良い考えですか?それはまだ一般的に均等に分散されたランダムですか? それぞれthreadRandomが で種付けされているというinitRandomことは、一様分布を崩していませんか?

再現可能な理由から、1 つのグローバル ランダムを共有することはできません。実行によっては、一部のスレッドが他のスレッドよりも高速に実行される可能性があるため、常に同じ順序でグローバル ランダムを呼び出すとは限らないためです (競合によってパフォーマンスが低下する可能性があります)。

4

2 に答える 2

1

具体的には、均一な分布については、10 ピクセルごとに 1 つのランダムな位置で問題ないようです。

分布

ちょっと待って、1 ピクセルあたり 1 つのランダムな位置を使用すると、シードされたスレッド化アプローチの方がさらに優れているように見えます!? 完全に均一な分布 (サイズ 250000 の場合) では、すべて黒になります。

ここに画像の説明を入力

左:

public class SingleRandomProof extends JFrame {

    public static final int WIDTH = 500;
    public static final int HEIGHT = 500;
    public static final int SIZE = WIDTH * HEIGHT;

    public static void main(String[] args) {
        SingleRandomProof proof = new SingleRandomProof();
        proof.pack();
        proof.setVisible(true);
        proof.doCalc();
    }

    private JLabel panel;

    public SingleRandomProof() throws HeadlessException {
        super("1 random");
        BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
        panel = new JLabel(new ImageIcon(image));
        setContentPane(panel);
    }

    private void doCalc() {
        BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
        Graphics g = image.getGraphics();
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, WIDTH, HEIGHT);
        g.setColor(Color.BLACK);
        Random r = new Random(37);
        for (int i = 0; i < SIZE; i++) {
            int position = r.nextInt(SIZE);
            g.fillRect(position % HEIGHT, position / HEIGHT, 1, 1);
        }
        panel.setIcon(new ImageIcon(image));
    }

}

右:

public class SeededThreadRandomProof extends JFrame {

    public static final int WIDTH = 500;
    public static final int HEIGHT = 500;
    public static final int SIZE = WIDTH * HEIGHT;

    public static void main(String[] args) {
        SeededThreadRandomProof proof = new SeededThreadRandomProof();
        proof.pack();
        proof.setVisible(true);
        proof.doCalc();
    }

    private JLabel panel;

    public SeededThreadRandomProof() throws HeadlessException {
        super("10 seeded randoms");
        BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
        panel = new JLabel(new ImageIcon(image));
        setContentPane(panel);
    }

    private void doCalc() {
        BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
        Graphics g = image.getGraphics();
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, WIDTH, HEIGHT);
        g.setColor(Color.BLACK);
        Random initRandom = new Random(37);
        for (int j = 0; j < 10; j++) {
            Random r = new Random(initRandom.nextLong());
            for (int i = 0; i < SIZE / 10; i++) {
                int position = r.nextInt(SIZE);
                g.fillRect(position % HEIGHT, position / HEIGHT, 1, 1);
            }
        }
        panel.setIcon(new ImageIcon(image));
    }

}
于 2016-09-01T13:47:07.327 に答える
1

ランダムを介して数値の均等な分布が得られますが、リスト内の計算オブジェクトの各リストが実行される順序は保証されていないため、これらが結果を共有リストに渡す場合、順序は実行ごとに異なる場合があります。

于 2016-08-31T15:51:29.537 に答える