Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ OpenMP和内核/线程_C++_Parallel Processing_Cpu_Openmp_Memory Bandwidth - Fatal编程技术网

C++ OpenMP和内核/线程

C++ OpenMP和内核/线程,c++,parallel-processing,cpu,openmp,memory-bandwidth,C++,Parallel Processing,Cpu,Openmp,Memory Bandwidth,我的CPU是一个核心i330m,有2个核心和4个线程。当我在终端中执行命令cat/proc/cpuinfo时,就好像我有4个CPU。当我使用OpenMP函数时,我也得到了4 现在我有一个标准C++向量类,我是指不使用表达式模板的固定大小的双数组类。我仔细地将类中的所有方法并行化,得到了“预期”的加速 问题是:在这种简单的情况下,我能猜出预期的加速吗?例如,如果我添加两个向量而不并行化For循环,我会得到一些时间(使用shell time命令)。现在,如果我使用OpenMP,根据内核/线程的数量,

我的CPU是一个核心i330m,有2个核心和4个线程。当我在终端中执行命令cat
/proc/cpuinfo
时,就好像我有4个CPU。当我使用OpenMP函数时,我也得到了4

现在我有一个标准C++向量类,我是指不使用表达式模板的固定大小的双数组类。我仔细地将类中的所有方法并行化,得到了“预期”的加速

问题是:在这种简单的情况下,我能猜出预期的加速吗?例如,如果我添加两个向量而不并行化For循环,我会得到一些时间(使用shell time命令)。现在,如果我使用OpenMP,根据内核/线程的数量,我应该得到时间除以2还是除以4?我要强调的是,我只是在问这个特殊的简单问题,数据中没有相互依赖关系,一切都是线性的(向量加法)

下面是一些代码:

Vector Vector::operator+(const Vector& rhs) const
{
    assert(m_size == rhs.m_size);
    Vector result(m_size);
    #pragma omp parallel for schedule(static)
    for (unsigned int i = 0; i < m_size; i++) 
            result.m_data[i] = m_data[i]+rhs.m_data[i];

    return result;
}
向量向量::运算符+(常量向量和rhs)常量
{
断言(m_大小==rhs.m_大小);
向量结果(m_大小);
#计划的pragma omp并行(静态)
for(无符号整数i=0;i
我已经读过这篇文章:

我希望有人能告诉我更多关于OpenMP是如何在这个简单的案例中完成工作的。我应该说我是并行计算的初学者


谢谢

编辑:现在添加了一些代码

在那个特定的例子中,计算量很小,内存访问量很大。因此,性能将在很大程度上取决于:

  • 向量的大小
  • 你是如何计时的。(是否有用于计时的外环)
  • 数据是否已在缓存中
对于较大的向量大小,您可能会发现性能受到内存带宽的限制。在这种情况下,并行性不会有多大帮助。对于较小的尺寸,线程开销将占主导地位。如果您正在获得“预期”的加速,那么您可能处于两者之间的某个位置,结果是最佳的

我拒绝给出硬性数字,因为一般来说,“猜测”性能(特别是在多线程应用程序中)是一个失败的原因,除非您事先具备测试知识或熟悉程序及其运行系统

正如我在这里回答的一个简单例子:

在3.5 GHz的i7 920内核上(4个内核,8个线程):

如果使用4个线程运行,结果是:

This machine calculated all 78498 prime numbers under 1000000 in 39.3498 seconds
This machine calculated all 78498 prime numbers under 1000000 in 30.4429 seconds
如果使用4个线程运行,并显式(使用任务管理器)将线程固定在4个不同的物理内核上,结果是:

This machine calculated all 78498 prime numbers under 1000000 in 39.3498 seconds
This machine calculated all 78498 prime numbers under 1000000 in 30.4429 seconds


因此,这表明即使是对于一个非常简单且令人尴尬的并行应用程序,它也是多么不可预测。涉及大量内存使用和同步的应用程序变得更加丑陋…

这是神秘的答案。您的问题纯粹是内存带宽受限。看一看这张照片。在您的计算机上以单线程和多线程的方式运行它,并查看三元组结果-这就是您的情况(好吧,几乎是这样,因为您的输出向量同时也是您的输入向量之一)。计算移动的数据量,您将准确地知道预期的性能

多线程可以解决这个问题吗?对很少有一个CPU内核会使系统的整个内存带宽饱和。现代计算机平衡可用内存带宽和可用内核数量。根据我的经验,通过简单的memcopy操作,您将需要大约一半的内核来饱和内存带宽。如果您在途中进行一些计算,可能还需要一些时间

请注意,在NUMA系统上,您需要将线程绑定到cpu内核,并使用本地内存分配来获得最佳结果。这是因为在这样的系统上,每个CPU都有自己的本地内存,访问速度最快。您仍然可以像在普通SMP上一样访问整个系统内存,但这会带来通信成本—CPU必须显式地交换数据。将线程绑定到CPU并使用本地分配是非常重要的。如果做不到这一点,将破坏可伸缩性。如果要在Linux上执行此操作,请检查libnuma