2015-01-20 70 views
2

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

我已经想到了两种方法可以做到这一点:

  • 将呈现组件到一个线程。有一些事情 我需要改变,但我有一个好主意,需要做什么 。
  • 使用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; 
    } 

}

+0

你可以发布你正在考虑多线程的代码吗? – 2015-01-20 23:23:30

+0

最好的结果取决于这些部件是如何并行化的,以及你梳理出并行性的能力,以便它可以被利用。没有调查代码就无法回答问题。 – 2015-01-20 23:29:34

+0

@MichaelB。它有点长,因为它包含多种功能,但如果有必要,我会制作一个pastebin链接。 – MKII 2015-01-20 23:30:09

回答

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位的竞争条件。在这种情况下,低级并行可能是更好的选择。

+0

我没有看到任何方式可以每行调用一次,而无需执行其他会降低性能的其他任何操作。此外,这是渲染,我唯一处理图形的时候是将视图缓冲区写入屏幕。 – MKII 2015-01-23 02:32:19

+0

@MKII我没有注意到当alpha字节不为零时你只写入dest - 你可能仍然从删除对memcpy的调用中受益,例如编辑 – gordy 2015-01-23 03:44:40

+0

我会花时间但我会打赌分支的成本比仅仅写出不会被看到的代价更昂贵。如果您的源代码中的大部分已知包含alpha,则可以实现一种算法,该算法将允许您跳过帧的大部分区域。 – rparolin 2015-01-23 05:26:08

0

从理论上讲,它们应该产生相同的效果。实际上,这可能是完全不同的。

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

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