2

首先,我对多线程知之甚少,我很难找到优化此代码的最佳方法,但多线程似乎是我应该走的道路。

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”循环同时运行以获取不同的“平面”值。这甚至可能吗?如果是这样,它真的会让我的程序更快吗?

4

5 回答 5

4

我也会研究 OpenMP。这是一个很棒的库,它允许使用编译指示以非常简单的方式进行线程化。OpenMP 可在许多平台上编译,您只需确保您的平台支持它!

我有一组代码,它有 8 个级别的 for 循环,并且它的线程非常好。

于 2013-03-28T19:26:18.833 回答
2

是的,这是完全可能的。在这种情况下,您应该摆脱事件而不用担心访问同步(即竞争条件),因为两个线程将在不同的数据集上运行。

这肯定会加速你在多核机器上的代码。

您可能想查看跨平台线程实现的std::thread(如果您对 c++ 11 没问题)(因为您尚未指定目标平台)。或者更好的线程支持库

您还可以考虑检测内核数量并启动适当数量的线程,如 threadcount = min(planes, cores) 并为每个工作函数提供对单个平面数据集的访问权限。

于 2013-03-28T19:19:47.863 回答
0

看起来你可以把它分成线程,你可能会看到一个很好的速度提升。但是,您的编译器已经在尝试为您展开循环并通过矢量化指令获得并行性。您的收益可能没有您想象的那么大,尤其是当您使用来自不同位置的读取使内存总线饱和时。

您可能会考虑的是,如果这是一个 2d 图形操作,请尝试使用 OpenGL 或类似的东西,因为它将利用您系统上的硬件,并且内置了一些并行性。

于 2013-03-28T19:24:49.177 回答
0

线程版本的代码会比简单的实现慢。因为在线程版本中,同步会花费很多时间。同样在线程版本中,您将有缓存性能缺陷。

也很有可能,for具有 3 遍的外循环将被编译器展开并并行执行。

您可以尝试制作线程版本并比较性能。无论如何,这将是有用的经验。

于 2013-03-28T19:28:55.293 回答
0

对于这种情况,您可能会比使用自动将 for 循环转换为线程的编译器做得更糟。

使用这样的代码,编译器可以确定是否存在任何迭代间数据依赖关系。如果不是,那么它知道它可以安全地将 for 循环拆分到多个线程中,将标准线程同步放在最后。通常,这样的编译器能够插入代码,在运行时确定线程的开销是否会被好处所抵消。

唯一的问题是,你有编译器吗?如果是这样,那么它是迄今为止获得线程好处的最简单方法,以实现像这样的直接、几乎公开的并行性。

我知道 Sun 的 C 编译器可以做到这一点(我认为他们是最早这样做的人之一。它可能只在他们的编译器的 Solaris 版本上)。我认为英特尔的编译器也可以。我对 GCC 有疑问(尽管我很乐意在这一点上得到纠正),而且我不太确定 Microsoft 的编译器。

于 2013-03-28T21:35:15.050 回答