java - 多线程时灰度图像算法比顺序慢
问题描述
对于学校项目,我们需要多线程图像处理算法。我决定将图像的高度除以线程数。每个线程循环通过高度和宽度并改变像素的颜色。奇怪的是,顺序版本总是快得多。我究竟做错了什么?
线程执行的方法:
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;
当我使用非常大的图像时,并行时间似乎比顺序图像提高了 0.5 秒,但是当我不保存结果时,并行算法再次变慢。
解决方案
问题是您的applyGrayScale()
方法是synchronized
- 只有一个线程可以同时执行它,因为它们都在同一个对象上运行它。您的代码中没有可以并行运行的部分。因此,基本上该过程与顺序变体中的过程或多或少相同,但是您为上下文切换和跟踪哪个线程进入该方法增加了一些额外的开销。
相反,您必须事先拆分图像 - 在创建线程时“告诉”他们应该修改哪个部分。然后将方法从正常更改synchronized
为正常并让他们并行完成工作。
推荐阅读
- r - 最后使用 plotly() 时隐藏 scale_color_manual() 中的特定图例
- c++ - 使用 rdkafkacpp.h 的 C++ 中的基本 Kafka Consumer
- avfoundation - 在 iOS 上安排音频样本播放
- sequelize.js - 为什么 Sequelize 会创建一个名为“文本”的数据库列,而不是以模型属性命名
- assembly - 将索引寄存器分配给通用寄存器
- python - 使用numpy时相应地迭代2个数组的最佳方法是什么?
- css - 如何制作灵活的网格 css/react
- css-selectors - 通过 css-selector 或 xpath 在 DOM 中查找部分文本
- c# - 使用 Newtonsoft JSON 指定要编码和解码的属性和字段
- ios - 将带有相机叠加层的 CMSampleBufferGetImageBuffer 裁剪为 UIImage