Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.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
Multithreading 为什么使用OpenMP进行计算比使用单个线程花费的时间多100倍?_Multithreading_Parallel Processing_Openmp - Fatal编程技术网

Multithreading 为什么使用OpenMP进行计算比使用单个线程花费的时间多100倍?

Multithreading 为什么使用OpenMP进行计算比使用单个线程花费的时间多100倍?,multithreading,parallel-processing,openmp,Multithreading,Parallel Processing,Openmp,我试图用OpenMP测试Pi计算问题。我有以下代码: #pragma omp parallel private(i, x, y, myid) shared(n) reduction(+:numIn) num_threads(NUM_THREADS) { printf("Thread ID is: %d\n", omp_get_thread_num()); myid = omp_get_thread_num(); printf("Thread myid is: %d\n", myid); f

我试图用OpenMP测试Pi计算问题。我有以下代码:

#pragma omp parallel private(i, x, y, myid) shared(n) reduction(+:numIn) num_threads(NUM_THREADS)
{
printf("Thread ID is: %d\n", omp_get_thread_num());
myid = omp_get_thread_num();
printf("Thread myid is: %d\n", myid);

  for(i = myid*(n/NUM_THREADS); i < (myid+1)*(n/NUM_THREADS); i++) {
//for(i = 0; i < n; i++) {

    x = (double)rand()/RAND_MAX;

    y = (double)rand()/RAND_MAX;

    if (x*x + y*y <= 1) numIn++;

  }
printf("Thread ID is: %d\n", omp_get_thread_num());

}

  return 4. * numIn / n;

}
#pragma omp parallel private(i,x,y,myid)共享(n)缩减(+:numIn)num_线程(num_线程)
{
printf(“线程ID为:%d\n”,omp_get_Thread_num());
myid=omp_get_thread_num();
printf(“线程myid是:%d\n”,myid);
对于(i=myid*(n/NUM_线程);i<(myid+1)*(n/NUM_线程);i++){
//对于(i=0;i
了解数据如何传播到不同的线程以及openmp如何将它们收集回来是非常重要的。通常,在多个线程上运行的错误设计(具有跨线程的数据依赖性)会导致执行速度比单个线程慢。

rand()
stdlib.h
中的
不是线程安全的。在多线程环境中使用它会导致其隐藏状态变量出现争用情况,从而导致性能低下

事实上,下面的代码可以作为OpenMP演示很好地工作

$ gc -fopenmp -o pi pi.c -O3; time ./pi
pi: 3.141672

real    0m4.957s
user    0m39.417s
sys 0m0.005s
代码:

#包括
#包括
int main()
{
常数n=50000;
const int NUM_THREADS=8;
int numIn=0;
#pragma omp parallel用于缩减(+:numIn)num_线程(num_线程)
对于(int i=0;i对于(intj=0;j一般来说,我不会在没有优化的情况下比较时间

gcc -O3 -Wall -pedantic -fopenmp main.c
在Linux中,
rand()
函数不是线程安全的(但MSVC和我想mingw32使用与MSVC相同的C运行时库MSVCRT也可以),您可以使用
rand\r
为每个线程使用不同的种子。请参阅

通常,在并行化循环时,尽量避免定义块大小。只需使用
#pragma omp for schedule(shared)
。也不需要指定并行化循环中的循环变量是私有的(代码中的变量
i

请尝试以下代码

#include <omp.h>
#include <stdio.h>
#include <stdlib.h>

int main() {
    int i, numIn, n;
    unsigned int seed;
    double x, y, pi;

    n = 1000000;
    numIn = 0;

    #pragma omp parallel private(seed, x, y) reduction(+:numIn) 
    {
        seed = 25234 + 17 * omp_get_thread_num();
        #pragma omp for
        for (i = 0; i <= n; i++) {
            x = (double)rand_r(&seed) / RAND_MAX;
            y = (double)rand_r(&seed) / RAND_MAX;
            if (x*x + y*y <= 1) numIn++;
        }
    }
    pi = 4.*numIn / n;
    printf("asdf pi %f\n", pi);
    return 0;
}
#包括
#包括
#包括
int main(){
int i,numIn,n;
无符号整数种子;
双x,y,pi;
n=1000000;
numIn=0;
#pragma omp并行私有(seed,x,y)缩减(+:numIn)
{
seed=25234+17*omp_get_thread_num();
#pragma omp for

对于(i=0;我可能是rand()是由于多线程性能差造成的瓶颈吗?您不应该自己处理工作的重新分配,而是使用
#pragma omp for
。在查看代码之前,为什么不在打开优化的情况下给出结果。使用
-O3
或至少
-O2
。您提供的链接状态相反:都是
()
rand\u r
是多线程安全的。我认为MT-safe在这里的意思应该是“不与腐败竞争”——rand()锁定全局变量,从而降低性能。
rand\u r
也是可重入的,这意味着完全的重新执行安全性-它不使用任何全局计数器/存储,因此从一开始就突然重新输入函数可以获得相同的结果(与rand()不同)@John_West该链接是在你发表评论前2年提供的。内容可能已经改变了。。。
#include <omp.h>
#include <stdio.h>
#include <stdlib.h>

int main() {
    int i, numIn, n;
    unsigned int seed;
    double x, y, pi;

    n = 1000000;
    numIn = 0;

    #pragma omp parallel private(seed, x, y) reduction(+:numIn) 
    {
        seed = 25234 + 17 * omp_get_thread_num();
        #pragma omp for
        for (i = 0; i <= n; i++) {
            x = (double)rand_r(&seed) / RAND_MAX;
            y = (double)rand_r(&seed) / RAND_MAX;
            if (x*x + y*y <= 1) numIn++;
        }
    }
    pi = 4.*numIn / n;
    printf("asdf pi %f\n", pi);
    return 0;
}