并行与线程 - 性能

时间:2015-01-20 23:09:24

标签: c++ multithreading optimization parallel-processing

我一直在阅读这个主题,但我还没有能够找到我问题的具体答案。我有兴趣使用并行/多线程来提高我的游戏性能,但我听到了一些矛盾的事实。例如,多线程可能不会对游戏的执行速度产生任何改进。我

我想到了两种方法:

  • 将渲染组件放入线程中。有一些事情 我需要改变,但我很清楚需要做什么 完成。
  • 使用openMP并行化渲染功能。我已经有代码这样做,因此这可能是更容易的选择。

这是Uni评估,目标硬件是我的Uni计算机,它是多核(4核),因此我希望使用这些技术中的任何一种来实现一些额外的效率。

因此,我的问题如下:我应该选择哪一个?通常会产生最好的结果?

编辑:我的主要功能是并行化/多线程:

void Visualization::ClipTransBlit ( int id, Vector2i spritePosition, FrameData frame, View *view )
{
    const Rectangle viewRect = view->GetRect ();
    BYTE *bufferPtr = view->GetBuffer ();

    Texture *txt = txtMan_.GetTexture ( id );
    Rectangle clippingRect = Rectangle ( 0, frame.frameSize.x, 0, frame.frameSize.y );

    clippingRect.Translate ( spritePosition );
    clippingRect.ClipTo ( viewRect );
    Vector2i negPos ( -spritePosition.x, -spritePosition.y );
    clippingRect.Translate ( negPos );

    if ( spritePosition.x < viewRect.left_ ) { spritePosition.x = viewRect.left_; }
    if ( spritePosition.y < viewRect.top_ ) { spritePosition.y = viewRect.top_; }

    if (clippingRect.GetArea() == 0) { return; }

    //clippingRect.Translate ( frameData );

    BYTE *destPtr = bufferPtr + ((abs(spritePosition.x) - abs(viewRect.left_)) + (abs(spritePosition.y) - abs(viewRect.top_)) * viewRect.Width()) * 4; // corner position of the sprite (top left corner)
    BYTE *tempSPtr = txt->GetData() + (clippingRect.left_ + clippingRect.top_ * txt->GetSize().x) * 4;

    int w = clippingRect.Width();
    int h = clippingRect.Height();
    int endOfLine = (viewRect.Width() - w) * 4;
    int endOfSourceLine = (txt->GetSize().x - w) * 4;

    for (int i = 0; i < h; i++)
    {
        for (int j = 0; j < w; j++)
        {
            if (tempSPtr[3] != 0)
            {
                memcpy(destPtr, tempSPtr, 4);
            }

            destPtr += 4;
            tempSPtr += 4;
        }

        destPtr += endOfLine;
        tempSPtr += endOfSourceLine;
    }

}

2 个答案:

答案 0 :(得分:2)

而不是为每个像素调用memcpy而只考虑在那里设置值。调用函数的开销很多次可能会占据此循环的总执行时间。 E.g:

for (int i = 0; i < h; i++)
{
    for (int j = 0; j < w; j++)
    {
        if (tempSPtr[3] != 0)
        {
            *((DWORD*)destPtr) = *((DWORD*)tempSPtr);
        }

        destPtr += 4;
        tempSPtr += 4;
    }

    destPtr += endOfLine;
    tempSPtr += endOfSourceLine;
}

你也可以通过使用这里提到的一个技巧来避免条件avoiding conditionals - 在如此严格的循环条件下可能非常昂贵。

修改 至于同时运行ClipTransBlit的几个实例或内部并行化ClipTransBlit是否更好,我想说一般来说最好在尽可能高的级别实现并行化,以减少因设置而产生的开销(创建线程,同步)他们等等。)

在你的情况下,虽然看起来你正在绘制精灵,如果它们是重叠的,那么没有额外的同步你的高级线程可能会导致讨厌的视觉伪像甚至是检查alpha位的竞争条件。在这种情况下,低级并行可能是更好的选择。

答案 1 :(得分:0)

理论上,它们应该产生相同的效果。在实践中,它可能会有很大不同。

如果打印出OpenMP程序的汇编代码,OpenMP只会调用范围内的某些函数,如#pragma omp parallel ...。它类似于folk

OpenMP是面向并行计算的,另一方面,多线程更为通用。 例如,如果要编写GUI程序,则需要多线程(某些框架可能会隐藏它。它仍然需要多个线程)。但是,您永远不想使用OpenMP实现它。