我有一个多线程代码(Windows),使用pthread进行C ++中的线程化。
我有4个线程分割单个作业,这样每个作业都可以访问相当大的全局数组的1/4。
如果我在全局范围声明部分的特定点定义全局范围内数组的指针,我发现我可以将性能降低2倍 - 看起来好像我的全局声明的顺序对我来说很重要应用程序性能。
有没有人知道为什么?
以下是我的结果:
如果重要,我在全球范围内声明的指针是:
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
答案 0 :(得分:2)
正如Art在评论中所暗示的那样,我想你最终可能会得到False Sharing,即数据共享一个缓存行,而线程/核心因此无法有效工作。
您需要将每个线程写入的数据保持公平(64到256个字节左右),以便在使用多个线程时获得良好的效率。
您的数据访问/写入模式与指针和数据的外观如何?
<强>更新强>
我不是专家,但可能是1/4距离,模数缓存行大小,可能会使线程相互干扰。缓存关联尝试缓解此问题,但仍然如此。
另一个问题是,如果这些指针附近的数据不断更新。
像英特尔的VTune这样的好的剖析器应该有助于诊断它。
至于行为,我会根据你重新订购的东西来检测数据是否分配到不同的地址。指针周围的数据如何?
我认为通过分配比你需要的更多的内存并在适当的n字节边界上对齐块来完成缓解。如果问题不是数据,而是指针,则可以在64字节边界上对齐它们,或者在每个线程中保留它们的本地副本。
同样,我知道英特尔(在他们的IPP库中)有一个特定的STL分配器来帮助解决这个问题。阅读它应该对你有帮助。
文章“Avoiding and Identifying false sharing”是一个开头,有一些附加指针(heh;)。