首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在使用openmp时没有看到任何加速

在使用openmp时没有看到任何加速
EN

Stack Overflow用户
提问于 2015-08-23 14:27:45
回答 1查看 129关注 0票数 1

我是openmp的新手,正在尝试理解它的结构。

这是我写的一段简单的代码。(数字的平方)..

代码语言:javascript
运行
复制
#include <omp.h>
#include <stdio.h>

#define SIZE 20000
#define NUM_THREADS 50
int main(){

    int id;
    int output[SIZE];
    omp_set_num_threads(NUM_THREADS);
    double start = omp_get_wtime();
    #pragma omp parallel for
    //{
        //id = omp_get_thread_num();

        for (int i=0; i<SIZE;i++){
            id = omp_get_thread_num();
            //printf("current thread :%d of %d threads\n", id, omp_get_num_threads());
            output[i] = i*i;
        }
    //}
    double end = omp_get_wtime();

    printf("time elapsed: %f for %d threads\n", end-start, NUM_THREADS);
}

现在,改变线程的数量应该会减少时间。但实际上是在增加时间吗?我做错了什么?

EN

回答 1

Stack Overflow用户

发布于 2015-08-26 01:26:24

这很可能是因为您选择了要检查的问题。让我们来看看你的并行循环:

代码语言:javascript
运行
复制
#pragma omp parallel for
for (int i=0; i<SIZE;i++){
    id = omp_get_thread_num();
    output[i] = i*i;
}

您指定了50个线程,并声明您有16个核心。

串行情况会忽略OMP指令,并可以执行积极的循环优化。每个元素的i都是i*i,这是一个简单的乘法,它只依赖于循环索引。id是可以完全优化的。这可能是完全矢量化的,如果你的处理器是现代的,它可能可以在一条指令(单指令多数据)中进行4次乘法,这对size=2000来说意味着500次单指令多数据乘法(没有数据获取开销和高速缓存友好的存储)。这将是非常快的。

或者,让我们看看并行版本。您正在初始化50个线程--开销很大!您引入了许多上下文切换,因为即使您拥有处理器亲和性,您也已经超额订阅了您的核心。50个线程中的每一个都将运行循环的40次迭代。如果幸运的话,编译器稍微展开了一下循环,这样它就可以进行SIMD乘法的10次迭代。乘法,无论SIMD或非SIMD,仍然会很快。你最终得到的是相同数量的实际工作,所以每个处理器有1/16的工作,但是创建和销毁50个线程的开销产生了比并行增益更多的工作。这是一个不能从并行化中获益的很好的例子。

你要做的第一件事就是把你的线程数量限制在你的实际内核上。通过在执行时间中添加不必要的上下文切换,您不会获得任何好处。比核心更多的线程通常不会让它运行得更快。

你想做的第二件事是在你的循环中做一些更复杂的事情,并且做很多次(谷歌的例子,有很多)。在构建工作循环时,您还需要考虑缓存性能,因为构造不佳的循环不会很好地加速。

当您将工作更改为比线程开销更复杂、令人难堪的并行和出色的缓存性能时,您可以开始看到OpenMP的真正好处。你要做的最后一件事是对你的循环从串行到16个线程进行基准测试。例如:

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32163841

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档