OpenMP和核心/线程

时间:2012-02-15 11:07:56

标签: c++ parallel-processing cpu openmp memory-bandwidth

我的CPU是Core i3 330M,有2个内核和4个线程。当我在终端中执行命令cat /proc/cpuinfo时,就好像我有4个CPUS。当我使用OpenMP函数get_omp_num_procs()时,我也得到了4.

现在我有一个标准的C ++矢量类,我的意思是一个不使用表达式模板的固定大小的双数组类。我仔细地并行化了我班级的所有方法,并得到了预期的#34;加速。

问题是:在这么简单的情况下,我能猜出预期的加速吗?例如,如果我添加两个没有并行化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;
}

我已经阅读过这篇文章:OpenMP thread mapping to physical cores

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

谢谢!

2 个答案:

答案 0 :(得分:3)

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

在该特定示例中,计算量很少且内存访问量很大。因此,性能将在很大程度上取决于:

  • 向量的大小。
  • 你如何计时。 (你有一个外环用于计时)
  • 数据是否已存在于缓存中。

对于较大的矢量大小,您可能会发现性能受内存带宽的限制。在这种情况下,并行性不会有太大帮助。对于较小的尺寸,线程的开销将占主导地位。如果你得到了“预期的”加速,你可能介于结果最佳的位置之间。

我拒绝提供硬数字,因为一般来说,“猜测”性能,特别是在多线程应用程序中是一个失败的原因,除非您具有先前的测试知识或对其运行的程序和系统的深入了解。 / p>

就像我在这里回答的一个简单例子:How to get 100% CPU usage from a C program

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

如果我使用 4个帖子运行,结果是:

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

如果我使用 4个线程并且明确地(使用任务管理器)固定4个不同物理核心上的线程,结果是:

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

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

答案 1 :(得分:1)

添加到Mysticals的答案。你的问题纯粹是内存带宽有限。看看STREAM benchmark。在单线程和多线程情况下在您的计算机上运行它,并查看三元组结果 - 这是您的情况(好吧,差不多,因为您的输出向量同时是您的输入向量之一)。计算您移动的数据量,您将确切地知道预期的性能。

多线程是否适用于此问题?是。单个CPU内核很少能够使系统的整个内存带宽饱和。现代计算机平衡可用内存带宽与可用内核数量。根据我的经验,您需要大约一半的内核才能通过简单的memcopy操作来满足内存带宽。如果你在路上做一些计算,可能还需要一些。

请注意,在NUMA系统上,您需要将线程绑定到cpu内核并使用本地内存分配来获得最佳结果。这是因为在这样的系统上,每个CPU都有自己的本地内存,访问速度最快。您仍然可以像通常的SMP一样访问整个系统内存,但这会产生通信成本 - CPU必须明确地交换数据。将线程绑定到CPU并使用本地分配非常重要。如果不这样做会导致可扩展性丧失。如果你想在Linux上执行此操作,请检查libnuma。