2017-01-27 7 views
-1

私は同期ブロックを使用してJavaでおもちゃプログラムを作成しています。私は1000x1000の画像の中のランダムなピクセルを選び、それをPixelatorの色に割り当てるn "Pixelator"スレッドを持っています。各ピクセルは1回のみ割り当てることができます。同期メソッドを使用してイメージに書き込むラッパークラスを使用して、bufferedImageに書き込みます。しかし、1つ以上のスレッドでテストすると、スピードアップは見えません。それがなぜ起こるのかについてのヒントはありますか?なぜ複数のスレッドでスピードアップしないのですか?

Relavantコード:

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; 
     } 
    } 
} 
+6

あなたのsetColorが同期されているためですか? – user2677821

+1

[mcve]を投稿してください。 – shmosel

+0

@ user2677821どのようにして、2つのスレッドが同時に同期されずに同じピクセルに書き込まれないようにするには? – ProgrammedChem

答えて

0

これは、スレッドを管理するためにマシンに一定の時間を要します。画像処理では、1つではなく2つのスレッドを使用し、処理時間を50%短縮するのではなく、処理に応じて30%から40までの間で行います(自分のJavaライブラリのマルチスレッドクラスの経験による見積もり)。

さらに、あなたの場合、単純な計算だけでは大した処理をしません。したがって、スレッドを管理する方が、単一スレッドで処理するよりも時間がかかります。大きな畳み込みをしてみてください。

0

あなたが直面している最大の問題は、スレッドを増やしてもシステムのメモリ帯域幅は増えないということです。

あなたのスレッドは、乱数を計算してメモリに書き出す以外は何もしません。より多くのスレッドを追加することで、乱数を計算する速度が向上する可能性がありますが、これはおそらくかなり速いものでした。 Math.random()は、暗号品質の乱数ジェネレータではありません。おそらく非常にです。

残念ながら、すべてのバイトがメモリに書き出されるまで、あなたの仕事は完了しません。あなたのシステムにはメモリバスが1つしかなく、高速にしか動きません。すべてのスレッドは、そのリソースに対して競合しなければなりません。

関連する問題