2017-01-27 16 views
-1

Я создаю игрушку в java, используя синхронизированный блок. У меня есть n потоков «Pixelator», которые выбирают случайный пиксель в изображении 1000x1000 и присваивают его цвету Pixelator. Каждый пиксель может быть назначен только один раз. Я пишу в bufferedImage, используя класс-оболочку, который использует синхронизированный метод для записи на изображение. Однако, когда я тестирую более одного потока, я не вижу ускорения. У вас есть намек на то, почему это было бы?Почему нет ускорения с несколькими потоками?

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 Как я могу убедиться, что два потока не записываются в один и тот же пиксель одновременно без синхронизации? – ProgrammedChem

ответ

0

Это требует определенного количества времени, чтобы машины для управления потоками. При обработке изображений используйте два потока вместо одного, не уменьшает время обработки на 50%, а от 30% до 40 в соответствии с обработкой (эмпирическая оценка с многопоточными классами моей собственной java-библиотеки).

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

0

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

Ваши потоки ничего не делают, кроме случайных чисел и записывают их в память. Добавление большего количества потоков потенциально увеличивает скорость, с которой вы можете вычислить случайные числа, но это, вероятно, было довольно быстро начать. Math.random() не является генератором случайных чисел криптовариантного качества. Вероятно, это очень быстро.

К сожалению, ваша работа выполняется не до тех пор, пока все байты не будут записаны в память. Ваша система имеет только одну шину памяти, и она может работать только так быстро. Все потоки должны бороться за этот ресурс.