- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在进行分子动力学仿真,并且为并行实现它已经进行了相当长的时间,尽管我成功加载了4线程处理器,但是并行计算的时间却大于并行计算的时间。串行模式。
在研究每个线程在哪个时间点开始和结束其循环迭代时,我注意到了一种模式:好像不同的线程在互相等待。
那时,我将注意力转向了程序的结构。我有一个类,该类的实例代表我的粒子系统,其中包含有关粒子的所有信息以及一些使用此信息的函数。我还有一个代表我的原子间势的类实例,其中包含势函数的参数以及一些函数(这些函数之一计算两个给定粒子之间的力)。
因此,在我的程序中,存在两个不同类的实例,并且它们彼此交互:一个类的某些功能引用了另一个类的实例。
我尝试并行实现的块如下所示:
void Run_simulation(Class_system &system, Class_potential &potential, some other arguments){
#pragma omp parallel for
for(…)
}
system
类的
Class_system
实例中的数据和
potential
类的
Class_potential
实例中的一些函数。
最佳答案
如果没有您的模拟类型的更多详细信息,我只能推测,所以这是我的推测。
您是否研究了负载平衡问题?我猜想循环将粒子分布在线程之间,但是如果您有某种有限的范围潜力,那么根据空间密度的不同,模拟体积在不同区域的计算时间可能会有所不同。这是分子动力学中非常普遍的问题,很难在分布式内存(大多数情况下为MPI)代码中正确解决。幸运的是,使用OpenMP,您可以直接访问每个计算元素上的所有粒子,因此负载平衡更容易实现。可以说,它不仅更简单,而且是内置的-只需使用for
子句更改schedule(dynamic,chunk)
指令的调度即可,其中chunk
是一个很小的数字,其最佳值可能因仿真而异。您可以将chunk
作为程序输入数据的一部分,或者改为编写schedule(runtime)
,然后通过将OMP_SCHEDULE
环境变量设置为"static"
,"dynamic,1"
,"dynamic,10"
,"guided"
等值来使用不同的调度类。
性能降低的另一个可能原因是错误共享和真实共享。当您的数据结构不适合并发修改时,就会发生错误共享。例如,如果您为每个粒子保留3D位置和速度信息(假设您使用速度Verlet积分器),则在给定IEEE 754 double 的情况下,每个坐标/速度三元组占用24个字节。这意味着一个64字节的高速缓存行可容纳2个完整的三元组,而另一个则占2/3。这样的结果是,无论您如何在线程之间分配粒子,总是至少会有两个线程共享一个缓存行。假设这些线程在不同的物理内核上运行。如果一个线程写入其高速缓存行的副本(例如,它更新粒子的位置),则将涉及高速缓存一致性协议(protocol),它将使另一线程中的高速缓存行无效,然后必须从中重新读取它即使是主内存中的缓存也较慢。当第二个线程更新其粒子时,这将使第一个内核中的缓存行无效。解决此问题的方法是使用适当的填充和适当的块大小选择,以便没有两个线程共享一个高速缓存行。例如,如果添加一个表面的第4维(可以使用它在位置 vector 的第4个元素中存储粒子的势能,在速度 vector 的第4个元素中存储动能)那么每个位置/速度四元组将占用32个字节,而恰好两个粒子的信息将放入一条高速缓存行中。如果然后在每个线程中分配偶数个粒子,则会自动消除可能的错误共享。
当线程同时访问同一数据结构,并且结构的各个部分之间存在重叠(由不同的线程修改)时,就会发生真正的共享。在分子动力学模拟中,这种情况经常发生,因为我们想利用牛顿第三定律,以便在处理成对的相互作用势时将计算时间减少为两个。当一个线程计算作用在粒子i
上的力时,在枚举其邻居j
时,计算j
施加在i
上的力会自动为您提供i
施加在j
上的力,这样就可以将作用力添加到j
的总力上。但是j
可能属于另一个线程,该线程可能正在同时对其进行修改,因此两个更新都必须使用原子操作(两者都是,如果另一个线程碰巧与自己的多个粒子中的一个相邻,则另一个线程可能会更新i
)。 x86上的原子更新是通过锁定指令实现的。这并没有经常出现的那么慢,但是仍然比常规更新慢。它还包括与错误共享相同的缓存行无效效果。为了解决这个问题,以增加内存使用为代价,可以使用局部数组来存储部分力的贡献,然后最终进行减少。减少本身必须与锁定指令以串行方式或并行方式执行,因此可能会发现,使用这种方法不仅没有 yield ,而且速度可能会更慢。适当的颗粒分类和在处理元件之间的巧妙分配,以最小化界面区域,可以用来解决这个问题。
我想谈谈的另一件事是内存带宽。根据您的算法,在循环的每次迭代中获取的数据元素的数量与浮点操作的数量之间存在一定的比率。每个处理器只有有限的带宽可用于内存提取,如果碰巧您的数据不太适合CPU缓存,则可能发生内存总线无法传递足够的数据来馈送如此多的线程在单个内存中执行的情况。插座。 Core i3-2370M的L3高速缓存只有3 MiB,因此,如果您明确保留每个粒子的位置,速度和力,则只能在L3高速缓存中存储大约43000个粒子,在L2高速缓存中只能存储大约3600个粒子(或大约1800个)每个超线程的粒子数)。
最后一个是超线程。正如高性能标记已经指出的那样,超线程共享大量的核心机制。例如,只有一个AVX vector FPU引擎在两个超线程之间共享。如果未对代码进行矢量化处理,则会损失处理器中大量可用的计算能力。如果您的代码是矢量化的,则这两个超线程将在争夺对AVX引擎的控制权时互相介入。仅当超线程能够通过将计算(在一个超线程中)与内存负载(在另一个超线程中)覆盖来隐藏内存延迟时,超线程才有用。借助密集的数字代码在执行内存加载/存储之前执行许多寄存器操作,超线程丝毫没有任何好处,您最好以一半的线程数量运行并将其显式绑定(bind)到不同的内核,以防止OS调度程序运行它们作为超线程。在这方面,Windows上的调度程序特别笨拙,请参阅here作为示例。英特尔的OpenMP实现支持通过环境变量控制的各种绑定(bind)策略。 GNU的OpenMP实现也是如此。我不知道在Microsoft的OpenMP实现中有什么方法可以控制线程绑定(bind)(也称为亲和力掩码)。
关于c++ - OpenMP和OOP(分子动力学仿真),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13958858/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!