全局变量的顺序改变了C ++ / OpenGL中的性能

时间:2014-02-07 13:32:50

标签: c++ c arrays multithreading opengl

我有一个多线程代码(Windows),使用pthread进行C ++中的线程化。

我有4个线程分割单个作业,这样每个作业都可以访问相当大的全局数组的1/4。

如果我在全局范围声明部分的特定点定义全局范围内数组的指针,我发现我可以将性能降低2倍 - 看起来好像我的全局声明的顺序对我来说很重要应用程序性能。

有没有人知道为什么?

以下是我的结果:

  • 单线程= 0.07秒
  • 4个线程= 0.02秒(当指向大数组的全局指针位于 全局声明的开始)
  • 4个线程= 0.04秒(当指向大数组的全局指针是 在全局声明中间)

如果重要,我在全球范围内声明的指针是:

GLbyte * render_flag; GLfloat * surface_primative;

正如我正确指出的那样,我应该评论这些测试的精确度非常高,它们可能有两个重要数字,但它们是高度一致的。

有没有人根据之前的全球声明顺序遇到性能差异?或者有人知道为什么这可能在理论上发生吗?

其他

我注意到(感谢来自SO的建议)我的线程使用的数组的数组指针声明直接在(在内存空间中)一些其他变量也被线程修改:

int number_of_tiles;        
int success_count_1;   ///Counters for successful searches
int success_count_2;
int success_count_3;
int success_count_4;

int offset;   

GLbyte* render_flag;   ///Pointer to array of render flags
GLfloat* surface_primative;   ///Pointer to surface primative array

如果我在指向数组的指针和计数器之间包含一些填充,我的代码会再次快速运行:

int number_of_tiles;        
int success_count_1;   ///Counters for successful searches
int success_count_2;
int success_count_3;
int success_count_4;
int offset;

char padding[100];   

GLbyte* render_flag;   ///Pointer to array of render flags
GLfloat* surface_primative;   ///Pointer to surface primative array

1 个答案:

答案 0 :(得分:2)

正如Art在评论中所暗示的那样,我想你最终可能会得到False Sharing,即数据共享一个缓存行,而线程/核心因此无法有效工作。

您需要将每个线程写入的数据保持公平(64到256个字节左右),以便在使用多个线程时获得良好的效率。

您的数据访问/写入模式与指针和数据的外观如何?

<强>更新

我不是专家,但可能是1/4距离,模数缓存行大小,可能会使线程相互干扰。缓存关联尝试缓解此问题,但仍然如此。

另一个问题是,如果这些指针附近的数据不断更新。

像英特尔的VTune这样的好的剖析器应该有助于诊断它。

至于行为,我会根据你重新订购的东西来检测数据是否分配到不同的地址。指针周围的数据如何?

我认为通过分配比你需要的更多的内存并在适当的n字节边界上对齐块来完成缓解。如果问题不是数据,而是指针,则可以在64字节边界上对齐它们,或者在每个线程中保留它们的本地副本。

同样,我知道英特尔(在他们的IPP库中)有一个特定的STL分配器来帮助解决这个问题。阅读它应该对你有帮助。

文章“Avoiding and Identifying false sharing”是一个开头,有一些附加指针(heh;)。