首先,我对多线程知之甚少,而且我很难找到优化此代码的最佳方法,但多线程似乎是我应该采用的路径。
double
applyFilter(struct Filter *filter, cs1300bmp *input, cs1300bmp *output)
{
long long cycStart, cycStop;
cycStart = rdtscll();
output -> width = input -> width;
output -> height = input -> height;
int temp1 = output -> width;
int temp2 = output -> height;
int width=temp1-1;
int height=temp2 -1;
int getDivisorVar= filter -> getDivisor();
int t0, t1, t2, t3, t4, t5, t6, t7, t8, t9;
int keep0= filter -> get(0,0);
int keep1= filter -> get(1,0);
int keep2= filter -> get(2,0);
int keep3= filter -> get(0,1);
int keep4= filter -> get(1,1);
int keep5= filter -> get(2,1);
int keep6= filter -> get(0,2);
int keep7= filter -> get(1,2);
int keep8= filter -> get(2,2);
//Declare variables before the loop
int plane, row, col;
for (plane=0; plane < 3; plane++) {
for(row=1; row < height ; row++) {
for (col=1; col < width; col++) {
t0 = (input -> color[plane][row - 1][col - 1]) * keep0;
t1 = (input -> color[plane][row][col - 1]) * keep1;
t2 = (input -> color[plane][row + 1][col - 1]) * keep2;
t3 = (input -> color[plane][row - 1][col]) * keep3;
t4 = (input -> color[plane][row][col]) * keep4;
t5 = (input -> color[plane][row + 1][col]) * keep5;
t6 = (input -> color[plane][row - 1][col + 1]) * keep6;
t7 = (input -> color[plane][row][col + 1]) * keep7;
t8 = (input -> color[plane][row + 1][col + 1]) * keep8;
// NEW LINE HERE
t9 = t0 + t1 + t2 + t3 + t4 + t5 + t6 + t7 + t8;
t9 = t9 / getDivisorVar;
if ( t9 < 0 ) {
t9 = 0;
}
if ( t9 > 255 ) {
t9 = 255;
}
output -> color[plane][row][col] = t9;
} ....
所有这些代码很可能不是必需的,但它确实提供了一些上下文。因为3“for”循环中的第一个仅从0到2,我希望有一种方法可以将底部的两个“for”循环线程同时运行,以获得不同的“平面”值。这甚至可能吗?如果是这样,它会让我的程序更快吗?
答案 0 :(得分:3)
我也会研究OpenMP。它是一个很棒的库,允许使用编译指示以非常简单的方式进行线程化。 OpenMP可以在许多平台上编译,你只需要确保你的支持它!
我有一组代码,它有8个for循环级别,并且非常好地处理它。
答案 1 :(得分:1)
是的,这是完全可能的。在这种情况下,您应该放弃事件而不必担心访问同步(即竞争条件),因为两个线程都将在不同的数据集上运行。
这肯定会加速你在多核计算机上的代码。
您可能希望查看std::thread(如果您对c ++ 11没问题)进行跨平台线程实现(因为您尚未指定目标平台)。或者更好地使用threading support library
您还可以考虑检测内核数量并启动适当数量的线程,如threadcount = min(plane,cores),并为每个worker函数提供对单个平面数据集的访问权。
答案 2 :(得分:0)
当然看起来你可以把它分解成线程,你可能会看到一个很好的速度提升。但是,您的编译器已经尝试为您展开循环并通过向量化指令获得并行性。您的收益可能没有您怀疑的那么多,特别是如果您使用来自不同位置的读取来使内存总线饱和。
你可能会考虑的是,如果这是一个2D图形操作,请尝试使用OpenGL或类似的,因为它会利用系统上的硬件,并且内置了一些并行性。
答案 3 :(得分:0)
代码的线程版本比简单实现慢。因为在线程版本中会有很多时间花在同步上。同样在线程版本中,您将具有缓存性能缺陷。
同样很有可能的是,具有3遍的外for
循环将由编译器展开并将并行执行。
您可以尝试制作线程版本并比较性能。无论如何,这将是有用的经验。
答案 4 :(得分:0)
对于这样的情况,你可能比使用自动将循环转换为线程的编译器更糟糕。
使用这样的代码,编译器可以确定是否存在任何迭代间数据依赖性。如果没有,那么它知道它可以安全地在多个线程之间拆分for循环,最后将bog标准线程同步。通常,这样的编译器能够插入代码,该代码在运行时确定具有线程的开销是否会被优势所抵消。
唯一的问题是,你有编译器吗?如果是这样的话那么它是迄今为止最简单的方法,可以获得线程的好处,就像这样直截了当,几乎是明显的并行性。
我知道Sun的C编译器会这样做(我认为他们是最早做这件事的人之一。它可能只在他们的编译器的Solaris版本上)。我认为英特尔的编译器也可以。我对GCC有疑问(虽然我很乐意在这一点上得到纠正),而且我对微软的编译器也不太了解。