繁体   English   中英

为什么一个以上的线程不能加速?

[英]Why no speedup with more than one thread?

我正在使用同步块在 java 中创建一个玩具程序。 我有 n 个“Pixelator”线程,它们在 1000x1000 图像中选择一个随机像素并将其分配给 Pixelator 的颜色。 每个像素只能分配一次。 我使用包装类写入 bufferedImage,该包装类使用同步方法写入图像。 但是,当我使用 1 个以上的线程进行测试时,我没有看到加速。 你有什么关于为什么会这样的提示吗?

相关代码:

import java.awt.Color;
import java.awt.image.*;
import java.io.*;

import javax.imageio.*;

import java.util.ArrayList;
import java.util.Random;

public class q2 {

    // The image constructed
    public static BufferedImage img;

    // Image dimensions; you could also retrieve these from the img object.
    public static int width;
    public static int height;

    // simplified method for stack overflow example
    public static int rgbFromN(int n) {
        return -16755216;
    }

    public static void main(String[] args) {
        Random r = new Random();
        try {
            // arg 0 is the width
            width = 1000;
            // arg 1 is the height
            height = 1000;
            // arg 2 is the number of threads
            int nt = 1;

            // create an image and initialize it to all 0's
            img = new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB);
            synchronizedIMG simg = new synchronizedIMG(img);
            for (int i=0;i<width;i++) {
                for (int j=0;j<height;j++) {
                    img.setRGB(i,j,0);
                }
            }


            Thread[] threads = new Thread[nt];
            long startTime = System.currentTimeMillis();
            for (int i = 0; i < threads.length; i++) {
                threads[i] = new Thread(new Pixelator(rgbFromN(i),width,height,((width*height)/nt),simg));    
                threads[i].start();
            }
            for (int i = 0; i < threads.length; i++) {   
                threads[i].join();
            }

            long endTime = System.currentTimeMillis();
            System.out.println("Time(ms): " + (endTime-startTime));

            // Write out the image
            File outputfile = new File("outputimage.png");
            ImageIO.write(img, "png", outputfile);

        } catch (Exception e) {
            System.out.println("ERROR " +e);
            e.printStackTrace();
        }
    }
}

class Pixelator implements Runnable {
    int color;
    int width;
    int height;
    int numPixels;
    int currentPixels = 0;
    synchronizedIMG simg;

    public Pixelator(int color, int width, int height,int numPixels, synchronizedIMG simg){
        this.color = color;
        this.width = width;
        this.height = height;
        this.numPixels = numPixels;
        this.simg = simg;
    }

    public void run() {
        int randomX = 0;
        int randomY = 0;
        boolean success = false;

        while(currentPixels < numPixels){
            randomX = 0 + (int)(Math.random() * (width));
            randomY = 0 + (int)(Math.random() * (height));
            success = simg.setColor(color, randomX, randomY);
            if(success){
                currentPixels++;
            }
        }
        return;
    }
}

class synchronizedIMG{
    BufferedImage img;

    public synchronizedIMG(BufferedImage img){
        this.img = img;
    }

    public synchronized boolean setColor(int color, int x, int y){
        if(img.getRGB(x, y) == 0){
            img.setRGB(x, y, color);
            return true;
        } else{
            return false;
        }
    }
}

机器需要一定的时间来管理线程。 在图像处理中,使用两个线程而不是一个线程,不会减少50%的处理时间,而是根据处理情况减少30%到40之间(用我自己的java库的多线程类经验估计)。

此外,在你的情况下,你不做任何主要的处理只是简单的计算。 因此,管理线程比在单个线程上进行处理要长。 尝试做一个大卷积。

您面临的最大问题是添加更多线程不会增加系统的内存带宽。

您的线程除了计算随机数并将它们写入内存之外什么都不做。 添加更多线程可能会提高计算随机数的速度,但这可能是非常快的开始。 Math.random() 不是加密质量的随机数生成器。 它可能非常快。

不幸的是,直到所有字节都写入内存后,您的工作才算完成。 您的系统只有一条内存总线,而且速度也只能如此之快。 所有线程都必须争夺该资源。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM