并行与线程 - 性能
Parallelism vs Threading - Performance
我一直在阅读有关该主题的内容,但未能找到我的问题的具体答案。我有兴趣使用 parallelism/multithreading 来提高我的游戏性能,但我听到了一些相互矛盾的事实。例如,多线程可能不会对游戏的执行速度产生任何改进。我
我想到了两种方法:
- 将渲染组件放入线程中。有些事情
我需要改变,但我很清楚需要改变什么
完成。
- 使用 openMP 并行化渲染功能。我已经编写了这样做的代码,因此这可能是更简单的选择。
这是一个 Uni 评估,目标硬件是我的 Uni 计算机,它们是多核(4 核),因此我希望使用其中任何一种技术来提高效率。
因此,我的问题如下:我应该选择哪一个?哪个通常会产生最好的结果?
编辑:主要功能我的意思是 parallelize/multithread 离开:
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;
}
}
与其为每个像素调用 memcpy,不如考虑只在此处设置值。多次调用函数的开销可能会支配此循环的整体执行时间。例如:
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 位时出现竞争条件。在那种情况下,低级并行性可能是更好的选择。
理论上,它们应该产生相同的效果。实际上,它可能完全不同。
如果您打印出 OpenMP 程序的汇编代码,OpenMP 只是调用范围内的一些函数,如 #pragma omp parallel ...
。它类似于 folk
.
OpenMP是面向并行计算的,另一方面,多线程更通用。
比如你要写一个GUI程序,多线程是必须的(有些框架可能隐藏了,还是需要多线程)。但是,您永远不想使用 OpenMP 来实现它。
我一直在阅读有关该主题的内容,但未能找到我的问题的具体答案。我有兴趣使用 parallelism/multithreading 来提高我的游戏性能,但我听到了一些相互矛盾的事实。例如,多线程可能不会对游戏的执行速度产生任何改进。我
我想到了两种方法:
- 将渲染组件放入线程中。有些事情 我需要改变,但我很清楚需要改变什么 完成。
- 使用 openMP 并行化渲染功能。我已经编写了这样做的代码,因此这可能是更简单的选择。
这是一个 Uni 评估,目标硬件是我的 Uni 计算机,它们是多核(4 核),因此我希望使用其中任何一种技术来提高效率。
因此,我的问题如下:我应该选择哪一个?哪个通常会产生最好的结果?
编辑:主要功能我的意思是 parallelize/multithread 离开:
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;
}
}
与其为每个像素调用 memcpy,不如考虑只在此处设置值。多次调用函数的开销可能会支配此循环的整体执行时间。例如:
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 位时出现竞争条件。在那种情况下,低级并行性可能是更好的选择。
理论上,它们应该产生相同的效果。实际上,它可能完全不同。
如果您打印出 OpenMP 程序的汇编代码,OpenMP 只是调用范围内的一些函数,如 #pragma omp parallel ...
。它类似于 folk
.
OpenMP是面向并行计算的,另一方面,多线程更通用。 比如你要写一个GUI程序,多线程是必须的(有些框架可能隐藏了,还是需要多线程)。但是,您永远不想使用 OpenMP 来实现它。