c - 为什么同一函数的第二次调用永远执行?
问题描述
我写了一个函数,它使用 aparallel for
用静态计划做一些计算,然后它返回到我的 main.js 中。之后,我再次调用这个函数,但这次它永远运行,所以我不得不中止程序。
#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);
}
我对标准输出进行了一些打印,它会在几秒钟内为第一次调用顺利打印每个线程的时间戳,但是当我进行第二次调用时,程序将永远执行并且没有任何打印。
我尝试了调度块大小为 n/thread_count 的块分布和块大小为 1 的块循环分布,但无论哪种方式我都遇到了同样的问题。
我还尝试复制该函数并一个接一个地调用具有相同内容的两个不同函数,但这也不起作用。
我没有更改两次调用之间的任何变量和数据,那么为什么第二个函数调用没有正确执行?
解决方案
您的代码存在一些问题,在函数my_function
中,循环的迭代没有按照您的意愿分配给线程。因为您再次将子句添加parallel
到#pragma omp for
,并假设您已禁用嵌套并行性(默认情况下),所以在外部并行区域中创建的每个线程都将“按顺序”执行该区域内的代码。因此,对于 an = 6
和number of threads = 4
,您将拥有以下代码块:
for (i=0; i<n; i++) {
work(a[i]);
}
正在执行6 x 4
=24
次(即循环迭代的总数乘以线程总数)。如需更深入的解释,请查看有关类似问题的SO Thread 。然而,下图提供了基本要素的可视化:
所以修复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];
最后一个问题是导致未定义的行为,这可能导致无法预料的问题。
另一个您可能知道或不知道的问题是具有讽刺意味的是,该功能work
实际上并没有做任何有意义的事情。
单独调用 double wtime = omp_get_wtime();
不会告诉您线程工作了多长时间。根据 OpenMP 文档
omp_get_wtime 例程以秒为单位返回经过的挂钟时间。
因此,要衡量在某些代码块中花费的时间,您可以执行以下操作
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;
}
}
推荐阅读
- php - 如果值为空或 NULL,PHP 多维数组按键和值搜索功能不起作用
- python - Django 在单独的池中多处理多个 API
- ios - 绘制具有动态值目标 c / swift 的折线图
- java - 将 java 接口覆盖方法转换为 kotlin 时,修饰符“覆盖”不适用于“本地函数”
- php - 如何在 DataDog 中关闭 nginx 日志收集?
- css - 如何在ejs中动态显示具有样式背景的图像
- javascript - 将单个对象与对象数组进行比较并返回匹配值对象的优化方法
- angular - 如何在Angular中将套接字结果显示为字符串而不是对象
- java - 全局定义 Lomboks @ExtensionMethod
- node.js - 我无法从服务器获取 json