题目:请利用OpenMP 中指令 reduction 编写程序实现对实数数组 x(i,j) = (i + j) / (i * j) (i,j = 1~100) 取最小值并指出最小值对应的下标。

解答思路:初步使用并行思路和reduction子句求出最小值,记录最小值所在的行和列下标。

#include <stdio.h>
#include <omp.h>
#include <time.h>
/*
请利用指令 reduction 编写程序实现对实数数组 x(i,j) = (i + j) / (i * j) (i,j = 1~10) 取最小值并指出最小值对应的下标。
*/#define m 100
#define n 100double x_min = 1000;
int min_i, min_j;
int i, j;double x[m + 1][n + 1];int main()
{clock_t start, finish;double Total_time;int tid, nthreads;start = clock();for (int i = 1; i <= m; i++){for (int j = 1; j <= n; j++){x[i][j] = (float)(i + j) / (i * j);}}omp_set_nested(1);omp_set_dynamic(0);omp_set_num_threads(20);
#pragma omp parallel for private(tid, nthreads, i, j) shared(x) reduction(min \: x_min)for (i = 1; i <= m; i++){for (j = 1; j <= n; j++){tid = omp_get_thread_num();nthreads = omp_get_num_threads();if (x[i][j] < x_min){x_min = x[i][j];min_i = i;min_j = j;}// printf("*****inner:tid = %d,nthreads = %d,x[%d][%d] = %lf\n", tid, nthreads, i, j, x[i][j]);}// printf("*****outer:tid = %d,nthreads = %d,x[%d][%d] = %lf\n", tid, nthreads, min_i, min_j, x_min);}printf("min:--------x[%d][%d] = %lf \n", min_i, min_j, x_min);// finish = clock();// Total_time = (double)(finish - start) / CLOCKS_PER_SEC; //单位换算成秒// printf("%f seconds\n", Total_time);return 0;
}

运行截图


存在的问题:以上程序求出的最小值是正确的,但是下标是有问题的,因为并行之后,不同的线程执行顺序是不固定的,reduction子句里面在进行规约的时候,只能把一个最值给正确拿到,但是i,j下标输出的确实最后一个执行的线程中的最小值的i,j下标。

所以我们可以初步使用最笨的方法,写一个查找函数,从二维数组找到最值,输出其i,j下标,但是很明显,这种方法的效率是很低的,与我们使用并行算法改进效率初衷相悖,代码如下:

#include <stdio.h>
#include <omp.h>
#include <time.h>
/*
请利用指令 reduction 编写程序实现对实数数组 x(i,j) = (i + j) / (i * j) (i,j = 1~10) 取最小值并指出最小值对应的下标。
*/#define m 100
#define n 100double x_min = 1000;
int min_i, min_j;
int i, j;double x[m + 1][n + 1];int *returnRes(double arr[m + 1][n + 1], double ele)
{int res[2] = {0};int *p = res;for (int i = 1; i <= m; i++){for (int j = 1; j <= n; j++){if (arr[i][j] == ele){res[0] = i;res[1] = j;}}}return p;
}int main()
{clock_t start, finish;double Total_time;int tid, nthreads;start = clock();for (int i = 1; i <= m; i++){for (int j = 1; j <= n; j++){x[i][j] = (float)(i + j) / (i * j);}}omp_set_nested(1);omp_set_dynamic(0);omp_set_num_threads(20);
#pragma omp parallel for private(tid, nthreads, i, j) shared(x) reduction(min \: x_min)for (i = 1; i <= m; i++){for (j = 1; j <= n; j++){tid = omp_get_thread_num();nthreads = omp_get_num_threads();if (x[i][j] < x_min){x_min = x[i][j];min_i = i;min_j = j;}// printf("*****inner:tid = %d,nthreads = %d,x[%d][%d] = %lf\n", tid, nthreads, i, j, x[i][j]);}// printf("*****outer:tid = %d,nthreads = %d,x[%d][%d] = %lf\n", tid, nthreads, min_i, min_j, x_min);}int *res = returnRes(x, x_min);printf("min:--------x[%d][%d] = %lf \n", res[0], res[1], x_min);// printf("min:--------x[%d][%d] = %lf \n", min_i, min_j, x_min);finish = clock();Total_time = (double)(finish - start) / CLOCKS_PER_SEC; //单位换算成秒printf("%f seconds\n", Total_time);return 0;
}

上面的returnRes函数就起到了返回最小值i,j下标的作用,通过在网上查找,我们得到了利用OpenMP reduction子句可以自定义规约函数,我们可以定义成结构体,里面分别是元素值,i下标,j下标,通过比较元素值来判断结构体的大小,从而整体返回一个结构体,这个时候下标也会一起返回出来。代码见下面:

#include <stdio.h>
#include <omp.h>
#include <time.h>
/*
请利用指令 reduction 编写程序实现对实数数组 x(i,j) = (i + j) / (i * j) (i,j = 1~10) 取最小值并指出最小值对应的下标。
*/#define m 100
#define n 100
double x[m + 1][n + 1];
struct compare
{float val;int index;int index1;
};
struct compare add_matrix(struct compare X, struct compare Y)
{struct compare temp;if (X.val < Y.val){temp.val = X.val;temp.index = X.index;temp.index1 = X.index1;}else{temp.val = Y.val;temp.index = Y.index;temp.index1 = Y.index1;}return temp;
}
int main()
{int tid, nthreads;for (int i = 1; i <= m; i++){for (int j = 1; j <= n; j++){x[i][j] = (float)(i + j) / (i * j);}}double x_mymin = 1000;int mymin_i, mymin_j;// omp_set_nested(1);omp_set_dynamic(0);omp_set_num_threads(10);struct compare mymin;mymin.val = x[1][1];mymin.index = 1;mymin.index1 = 1;int i = 1;int j = 1;clock_t begin, end;begin = clock();
#pragma omp declare reduction(p_add_matrix     \: struct compare \: omp_out = add_matrix(omp_out, omp_in)) initializer(omp_priv = {100}){#pragma omp parallel for private(tid, nthreads, i, j) shared(x) reduction(p_add_matrix \: mymin)for (i = 1; i <= m; i++){for (j = 1; j <= n; j++){tid = omp_get_thread_num();nthreads = omp_get_num_threads();if (x[i][j] < mymin.val){mymin.val = x[i][j];mymin.index = i;mymin.index1 = j;}// printf("*****inner:tid = %d,nthreads = %d,x[%d][%d] = %lf\n", tid, nthreads, i, j, x[i][j]);}// printf("*****outer:tid = %d,nthreads = %d,x[%d][%d] = %lf\n", tid, nthreads, mymin.index, mymin.index1, mymin.val);}}printf("mymin:--------x[%d][%d] = %lf ", mymin.index, mymin.index1, mymin.val);end = clock();double cost;cost = (double)(end - begin) / CLOCKS_PER_SEC;printf("CLOCKS_PER_SEC is %d\n", CLOCKS_PER_SEC);printf("time cost is: %lf secs\n", cost);return 0;
}

通过调节m,n的值可以测试程序运行的时间,会发现这种方式比单独写一个查找函数的方式要快非常多!下面有运行时间的截图哦,最后感谢我的舍友健神!

1.带查找函数的:(矩阵规模 10000*10000):1.3S左右

2.自定义规约函数的:(矩阵规模 10000*10000):0.4S左右,加速比提高了三倍多!

使用OpenMP reduction子句求解二维数组的最小值和输出所在下标相关推荐

  1. PHP 读取数据库内容并以二维数组按指定列输出实例

    最新PHP 读取数据库内容并以二维数组按指定列输出实例 以下是三零网为大家整理的最新PHP 读取数据库内容并以二维数组按指定列输出实例的文章,希望大家能够喜欢! <?php $host = &q ...

  2. Java黑皮书课后题第8章:*8.13(定位最大的元素)编写下面的方法,返回二维数组中最大元素的位置。返回值是包含两个元素的一维数组,这两个元素表示二维数组中最大元素的行下标和列下标

    *8.13(定位最大的元素)编写下面的方法,返回二维数组中最大元素的位置.返回值是包含两个元素的一维数组,这两个元素表示二维数组中最大元素的行下标和列下标 题目 题目描述与运行示例 破题 代码 题目 ...

  3. 二维数组主对角线与次对角线输出(C语言)

    源码如下: //二维数组主对角线与次对角线输出 #include <stdio.h> #include <stdlib.h> #define Nint main() {int ...

  4. 二维数组求最小值_05-最大子矩形-最大值减去最小值小于或等于num的子数组数量...

    年轻即出发... 简书:https://www.jianshu.com/u/7110a2ba6f9e 知乎:https://www.zhihu.com/people/zqtao23/posts Git ...

  5. php输出二维数组中指定内容,HP将MYSQL内容读到二维数组并按指定列输出

    <? $host = "localhost";   //主机名 $user = "root";        //mysql用户名 $password = ...

  6. 二维数组求最小值_求一列中满足条件的最大最小值

    [后台回复数字1-10,可查平台所有内容!] 最近碰到一个求最小值的问题,今天和大家分享一下.如下图: 想求张三的几次成绩的最高分和最低分. 我们先来看看最高分,这里大家先别往下看,想想如果是你,你怎 ...

  7. python输出杨辉三角啊二维数组_用Python输出一个杨辉三角的例子

    这篇文章主要介绍了用Python和erlang输出一个杨辉三角的例子,同时还提供了一个erlang版杨辉三角,需要的朋友可以参考下 关于杨辉三角是什么东西,右转维基百科:杨辉三角 稍微看一下直观一点的 ...

  8. Java学习笔记2.6.2 数组 - 二维数组

    文章目录 零.本讲学习目标 一.引入多维数组的场景 二.二维数组的定义 (一)指定二维数组行数与列数 (二)指定二维数组行数,不指定列数 (三)直接使用嵌套大括号"{}"静态初始化 ...

  9. 将一个3 * 4的二维数组转换为4 * 3的二维数组

    <程序设计基础-c语言>杨莉 刘鸿翔 ISBN-978-7-03-032903-5 p112 习题4 4.将一个3 * 4的二维数组的行和列的元素互换,存放到另一个4 * 3的二维数组中, ...

最新文章

  1. 从指纹到眼球识别:漫谈手机安全方案
  2. MySQL数据库之索引的应用
  3. mac 10.9.5 安装hadoop 1.2.1 运行wordcount
  4. 第一章 GuassDB数据库介绍
  5. ajax img标签,如何将属性添加到img标签以用于ajax调用
  6. Netflix是如何构建代码的
  7. Java与JavaScript的通信
  8. 记个SwitchButton笔记
  9. Adobe Flex Application LifeCycle
  10. 网游源码完整服务端_【每日源码】微人事是一个前后端分离的人力资源管理系统,项目采用SpringBoot+Vue开发。...
  11. php base64_decode 图片,php读取和保存base64编码图片
  12. Mybatis动态标签基本使用
  13. 如何使用计算机蓝牙设备管理器,电脑蓝牙bluetooth怎么使用_win7蓝牙bluetooth使用教程-系统城...
  14. 大数据第三季--Hbase(day6)-徐培成-专题视频课程
  15. 基于java宿舍管理系统的开题报告_基于Java的学生宿舍管理系统开题报告
  16. [收藏] 今天的存储解决方案:直连式存储(DAS)、存储区域网络(SAN)、网络接入存储(NAS)
  17. java compile方法_Java中带有示例的模式compile()方法
  18. 【最大流,最大匹配,最大独立集】2018.6.18 【2018提高组】模拟C组 T3 沙耶的玩偶
  19. TLV协议——实现封包与解析
  20. 【搬运及个人处理】联想电脑(Lenovo XiaoXinAir-14IIL 2020)散热模式Fn+Q 失效解决方案

热门文章

  1. 手机端页面自适应解决方案
  2. AD账号频繁被锁定原因
  3. 关于PCB行业三巨头的一点个人评价
  4. 华为项目管理工具与模板运用
  5. 一流在线课程申报表公共计算机,衡阳财经业职业技术学院精品课程建设申报表.doc...
  6. 业务指标基础分析(excel)--python实现
  7. React实战:留言板
  8. 【实战分享2】:如何基于OpenXR@ unity + 华为VR Glass 6dof Quest 开发跨平台VR游戏/应用
  9. Elasticsearch:跨集群复制 Cross-cluster replication(CCR)
  10. 极兔速递 一面面试题