c++ - 全局变量的顺序会改变 C++/OpenGL 中的性能

标签 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;

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

之前有人遇到过基于全局声明顺序的性能差异吗?或者有人知道理论上为什么会发生这种情况吗?

附加:

我注意到(感谢 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

最佳答案

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

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

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

更新

我不是专家,但 1/4 距离、模缓存行大小可能会使线程相互干扰。缓存关联试图减轻这种情况,但仍然如此。

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

一个好的分析器,比如 Intel 的 VTune 应该有助于诊断。

至于行为,我预计数据会根据您重新排序的方式分配在不同的地址上。指针周围的数据是什么样的?

我认为可以通过分配比您需要的稍多的内存并将 block 对齐到合适的 n 字节边界来减轻这种情况。如果问题不是数据,而是指针,您可以将它们对齐 64 字节边界,或者在每个线程中保留它们的本地拷贝。

同样,我知道 Intel(在他们的 IPP 库中)有一个特定的 STL 分配器来部分帮助解决这个问题。阅读相关内容应该会对您有所帮助。

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

关于c++ - 全局变量的顺序会改变 C++/OpenGL 中的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21629094/

相关文章:

php - 嵌套 foreach php

java - 如何在java中读取文本文件并将行分配给变量

C++ try catch 不适用于超出范围的数组

c++ - C++11 核心语言是否处理 Singleton Dead Reference?

c - 为什么 BLAS dsyrk 比简单的 C 实现更精确?

ios - HackerRink 解决方案重构代码 (Swift)

c++ - 关于未声明 TITLEBARINFO 的 MinGW 错误

c++ - 如何将字符串读入 vector

计算并删除数组 c 中的重复项

objective-c - 稳定的类似恒温器的算法,其中输入变化可能很大且突然