0

我有一段我前段时间写的代码。它的唯一目的是使用 openMP 进行实验。但我最近从 MacBook Pro Lion(2011 年初)切换到 MacBook Pro Mountain Lion(2013 年初)。如果它有助于获得更多其他信息的硬件,我很乐意给他们。该代码在旧代码上运行良好,这意味着 8 个线程在我的处理器上获得了 100%(98% 分钟)的负载。现在,在我的新机器上重新编译的相同代码只能获得 62% 的最大处理器负载。即使我提高线程。处理器负载均使用“istat pro”测量。

我的问题是什么会导致这种情况发生?

编辑:如果我删除 for in ,问题似乎就解决了#pragma omp parallel for shared(largest_factor, largest)。所以我明白#pragma omp parallel shared(largest_factor, largest) 了但我仍然不明白它为什么有效。

有问题的代码:

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

double fib(double n);

int main()
{
    int data[] = {124847,194747,194747,194747,194747,
                  194747,194747,194747,194747,194747,194747};
    int largest, largest_factor = 0;



    omp_set_num_threads(8);
    /* "omp parallel for" turns the for loop multithreaded by making each thread
     * iterating only a part of the loop variable, in this case i; variables declared
     * as "shared" will be implicitly locked on access
     */
    #pragma omp parallel for shared(largest_factor, largest)
    for (int i = 0; i < 10; i++) {
            int p, n = data[i];

            for (p = 3; p * p <= n && n % p; p += 2);
            printf("\n%f\n\n",fib(i+40));
            if (p * p > n) p = n;
            if (p > largest_factor) {
                    largest_factor = p;
                    largest = n;
                    printf("thread %d: found larger: %d of %d\n", 
                            omp_get_thread_num(), p, n);
            } 
            else 
            {
                    printf("thread %d: not larger:   %d of %d\n", 
                           omp_get_thread_num(),     p, n);
            }
    }

    printf("Largest factor: %d of %d\n", largest_factor, largest);
    return 0;
} 

double fib(double n)
{ 
if (n<=1)
{
    return 1;
}
else
{
    return fib(n-1)+fib(n-2);
}
}
4

1 回答 1

0

您没有看到所有线程都在使用的主要原因是每个线程花费不同的时间(由于递归函数或内部循环)并且您只有 10 次迭代。快速线程快速完成,然后只剩下几个线程可以运行。当你第一次运行你的代码时,它会 100% 开始运行,然后随着快速线程的完成和最后几个慢速线程仍在运行而下降。如果您将迭代次数更改为 100(并增加数据数组),您将看到 CPU 使用率保持在 100% 的时间会更长。我在您的代码中添加了一些计时打印输出。

此外,我认为您的共享变量存在竞争条件,因此我放入了一个关键部分。

要回答关于没有“for”语句的代码的问题,这样做是在八个不同的线程上运行相同的代码!它们不是运行特定迭代的线程,而是每个运行所有 10 次迭代。这不会比运行单个线程快,甚至可能更慢。

最后,由于每次迭代通常需要不同的时间,您应该像这样使用“schedual(dynamic)”

#pragma omp parallel for shared(largest_factor, largest) schedule(dynamic)

但是,由于您只有 10 次迭代,我认为在这种情况下不会有太大的不同。这是我对您的代码所做的操作,以了解发生了什么:

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

double fib(double n);

int main()
{
    int data[] = {124847,194747,194747,194747,194747,
                  194747,194747,194747,194747,194747,194747};
    int largest, largest_factor = 0;

    omp_set_num_threads(8);
    /* "omp parallel for" turns the for loop multithreaded by making each thread
     * iterating only a part of the loop variable, in this case i; variables declared
     * as "shared" will be implicitly locked on access
     */
    #pragma omp parallel for shared(largest_factor, largest)
    for (int i = 0; i < 10; i++) {
            int p, n = data[i];
        double time = omp_get_wtime();
        for (p = 3; p * p <= n && n % p; p += 2);
        printf("\n iteratnion %d, fib %f\n\n",i, fib(i+40));
        time = omp_get_wtime() - time;
        printf("time %f\n", time);

        if (p * p > n) p = n;
        #pragma omp critical
        {
           if (p > largest_factor) {        
              largest_factor = p;
              largest = n;      
              printf("thread %d: found larger: %d of %d\n", 
                    omp_get_thread_num(), p, n);
            } 
            else {
                printf("thread %d: not larger:   %d of %d\n", 
                        omp_get_thread_num(),     p, n);
            }
        }
    }

    printf("Largest factor: %d of %d\n", largest_factor, largest);
    return 0;
} 

double fib(double n) { 
if (n<=1) {
    return 1;
}
else {
    return fib(n-1)+fib(n-2);
}
}
于 2013-04-12T08:41:36.823 回答