gpt4 book ai didi

c - 为什么同一函数的第二次调用永远执行?

转载 作者:行者123 更新时间:2023-12-03 13:22:53 25 4
gpt4 key购买 nike

我写了一个函数,它使用 parallel for用静态时间表做一些计算,然后它返回到我的主。之后,我再次调用这个函数,但这次它永远运行,所以我不得不中止程序。

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

int thread_count;

void work(int x) {
int divisor = 0;
for (int i=1; i<=x; i++) {
if ((x%i) == 0) {
divisor++;
}
}
}

void initialize(int *codes, int n) {
thread_count = 4;

srand(time(NULL));
for (int i=0; i<n; i++) {
codes[i] = rand() % 10000;
}
}

double get_difference(double *times, int n) {
double min, max;
min = max = times[0];
for (int i=1; i<n; i++) {
if (times[i] > max) {
max = times[i];
}
if (times[i] < min) {
min = times[i];
}
}
return (max-min);
}

void my_function(int *a, double *times, int n, int thread_count) {
long i;
#pragma omp parallel
{
#pragma omp parallel for num_threads(thread_count) \
shared(a, n) private(i) schedule(static, 1)
for (i=0; i<n; i++) {
work(a[i]);
}
double wtime = omp_get_wtime();
printf( "Time taken by thread %d is %f\n", omp_get_thread_num(), wtime);
times[omp_get_thread_num()] = wtime;
}
}

void odd_even(int *a, int n) {
int phase, i, tmp;

# pragma omp parallel num_threads(thread_count) \
default(none) shared(a, n) private(i, tmp, phase)
for (phase = 0; phase < n; phase++) {
if (phase % 2 == 0)
# pragma omp for
for (i = 1; i < n; i += 2) {
if (a[i-1] < a[i]) {
tmp = a[i-1];
a[i-1] = a[i];
a[i] = tmp;
}
}
else
#pragma omp for
for (i = 1; i < n-1; i += 2) {
if (a[i] < a[i+1]) {
tmp = a[i+1];
a[i+1] = a[i];
a[i] = tmp;
}
}
}
}
在我的主要工作中,我会打电话:
int main(int argc, char *argv[]) {
int n = atoi(argv[1]);
int arr[n];
double times[thread_count];
initialize(arr, n);
odd_even(arr, n);
my_function(arr, times, n, thread_count);
double difference = get_difference(times, thread_count);
printf("Difference is %f\n", difference);

// my_function(arr, times, n, thread_count);
// difference = get_difference(times, thread_count);
// printf("Difference is %f\n", difference);
}
我对标准输出进行了一些打印,它会在几秒钟内为第一次调用顺利打印每个线程的时间戳,但是当我进行第二次调用时,程序将永远执行并且没有任何打印。
我尝试了调度 block 大小为 n/thread_count 的 block 分布和 block 大小为 1 的 block 循环分布,但无论哪种方式我都遇到了同样的问题。
我还尝试复制该函数并一个接一个地调用具有相同内容的两个不同函数,但这也不起作用。
我没有更改两次调用之间的任何变量和数据,那么为什么第二个函数调用没有正确执行?

最佳答案

您的代码存在一些问题,在函数 my_function 中循环的迭代没有按照您的意愿分配给线程。因为您再次添加了子句 parallel#pragma omp for ,并假设您已禁用嵌套并行性(默认情况下),在外部并行区域中创建的每个线程都将“按顺序”执行该区域内的代码。因此,对于 n = 6number of threads = 4 ,您将拥有以下代码块:

for (i=0; i<n; i++) {
work(a[i]);
}
正在执行 6 x 4 = 24次(即循环迭代的总数乘以线程总数)。如需更深入的解释,请查看 SO Thread关于类似的问题。然而,下图提供了基本要素的可视化:
enter image description here
所以修复 my_function到:
void my_function(int *a, double *times, int n, int thread_count) {
# pragma omp parallel num_threads(thread_count) shared(a)
{
#pragma omp for schedule(static, 1)
for (long i=0; i<n; i++) {
work(a[i]);
}
double wtime = omp_get_wtime();
printf( "Time taken by thread %d is %f\n", omp_get_thread_num(), wtime);
times[omp_get_thread_num()] = wtime;
}
}
二、变量被使用 thread_count在正确初始化之前:
double times[thread_count];
initialize(arr, n);
改成 :
initialize(arr, n);
double times[thread_count];
最后一个问题是导致 undefined behavior ,这可能会导致无法预料的问题。
另一个您可能知道或不知道的问题是具有讽刺意味的函数 work实际上并没有做任何有意义的事情。
调用 double wtime = omp_get_wtime();单独不会告诉你线程工作了多长时间。 According to the OpenMP documentation

The omp_get_wtime routine returns elapsed wall clock time in seconds.


因此,要衡量在某些代码块中花费的时间,您可以执行以下操作
double begin = omp_get_wtime();
// block of code
double end = omp_get_wtime();
并使用表达式 end-begin以秒为单位获得时间。在你的情况下:
 void my_function(int *a, double *times, int n, int thread_count) {
# pragma omp parallel num_threads(thread_count) shared(a)
{
double begin = omp_get_wtime();
#pragma omp for schedule(static, 1)
for (long i=0; i<n; i++) {
work(a[i]);
}
double end = omp_get_wtime();
double time = end - begin;
printf( "Time taken by thread %d is %f\n", omp_get_thread_num(), time);
times[omp_get_thread_num()] = time;
}
}

关于c - 为什么同一函数的第二次调用永远执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65753575/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com