hipy:
学校のプロジェクトのために我々は、画像処理アルゴリズムをマルチスレッドにする必要があります。私は、スレッドの数で画像の高さを分割することを決定しました。各スレッドは、高さと幅もループし、画素の色を変化させます。不気味しかし、シーケンシャルなバージョンは、はるかに高速に常にあります。何が私が間違っているのでしょうか?
スレッドによって実行される方法。
public synchronized void applyGrayScale(int numberOfThreads) {
int heightPerThread = imageHeight / numberOfThreads;
//Set the thread counter
int threadCounter = this.getCount();
this.setCount(count + 1);
/*The height per thread is calculated by the number of threads. We first start at 0. For the next thread we start at heightPerThread * [current thread number]
So for example; first thread runs from 0 to 80 pixels. The second thread runs from 81 to 160 pixels.
*/
for (int j = ((heightPerThread - 2) * threadCounter); j < (heightPerThread * (threadCounter + 1) - 1); j++) {
for (int i = 0; i < imageInput.getWidth() - 1; i++) {
//Get the RGB value and set it to grayscale
int rgb;
int p = RGB.getRGBW(imageInput, i, j);
rgb = (int) ((((p >> 16) & 0xFF) * 0.2125) + (((p >> 8) & 0xFF) * 0.7154) + ((p & 0xFF) * 0.0721));
rgb = (rgb << 16) | (rgb << 8) | (rgb);
//Set the new RGB value per pixel
imageOutput.setRGB(i, j, rgb);
}
}
}
プログラムを実行するコード:
int threadsAmount = 5;
final Thread[] threads = new Thread[threadsAmount];
BufferedImage image = null;
try {
image = ImageIO.read(new File("C:/Cat03.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
//Define the starting time
long start = System.currentTimeMillis();
//Create a new grayscale object and set the image
final GrayscaleParallel grayscaleParallel = new GrayscaleParallel(image);
//Thread to apply the grayscale with the number of threads
class grayScaleThread extends Thread {
@Override
public void run() {
grayscaleParallel.applyGrayScale(threadsAmount);
}
}
//Start all threads
for (int i = 0; i < threadsAmount; i++) {
threads[i] = new grayScaleThread();
threads[i].start();
}
//Wait for all threads to finish
for (int i = 0; i < threadsAmount; i++) {
try {
threads[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//save result to file
grayscaleParallel.createImage();
//Define how long it took
long end = System.currentTimeMillis();
float sec = (end - start) / 1000F;
System.out.println(sec + " seconds parallel");
出力は次のとおりです。0.897秒は、シリアル0.798秒を平行します
シーケンシャルなアルゴリズム:
for (int j = 0; j < _image.getHeight(); j++) {
for (int i = 0; i < _image.getWidth(); i++) {
int rgb;
int p = RGB.getRGBW(_image, i, j);
rgb = (int) ((((p >> 16) & 0xFF) * 0.2125) + (((p >> 8) & 0xFF) * 0.7154) + ((p & 0xFF) * 0.0721));
rgb = (rgb << 16) | (rgb << 8) | (rgb);
imageOutput.setRGB(i, j, rgb);
}
}
return imageOutput;
私は非常に大きな画像を使用する場合は、並列時間は、シーケンシャル1の上に0.5秒で改善するようだが、私は、並列アルゴリズムが再び遅くなる結果を保存しないとき。
Amongalen:
問題は、あなたのことであるapplyGrayScale()
方法があるsynchronized
-それらのすべてが同じオブジェクト上で、それを実行すると一つだけのスレッドが同時にそれを実行することができます。並列実行することができ、あなたのコード内のどの部分がありません。だから、basiclyプロセスは、多かれ少なかれ連続的な変異型と同じですが、あなたは、スレッドがメソッドに入るコンテキストスイッチと追跡のためのいくつかの余分なオーバーヘッドを追加します。
スレッドを作成するとき、それは変更する必要がありますどの部分にそれらを「伝える」 -その代わりに、手の前に画像を分割する必要があります。その後の方法を変えsynchronized
、正常にし、それらを並列に自分の仕事をしてみましょう。