6678_OpenMP学习笔记整理(一)——环境变量+嵌套并行

OpenMP API 用户指南
一、环境变量
1、OMP_SCHEDULE
有效类型:static、dynamic、guided、auto、sunw_mp_sched_reserved
若使用时设置为非有效类型,按默认static处理,不指定块大小,并发出warn

2、OMP_NUM_THTEADS
若指定值不是正整数,则忽略此变量,并发出warn
若工程中未设置此变量,则默认为处理器核心数,并≤32

3、OMP_DYNAMIC
类似于bool类型,值为true或false,缺省时默认为true,非法值时默认为ture,并发出warn

4、OMP_PROC_BIND(这部分我要再想想)
如果为 OMP_PROC_BIND 指定的值不是 TRUE、FALSE 或者逗号分隔的 master、close 或 spread 列表,则以非零状态退出进程。
如果无法将初始线程绑定到 OpenMP 位置列表中的第一个位置,则以非零状态退出进程。
如果未设置,则使用缺省值 FALSE。

5、OMP_PLACES
若设置的值无效,则以非零状态退出进程
若未设置,则使用缺省值 cores

6、OMP_NESTED
7、OMP_STACKSIZE
8、OMP_WAIT_POLICY
9、OMP_MAX_ACTIVE_LEVELS
10、OMP_THREAD_LIMIT
11、OMP_DISPLAY_ENV

二、Oracle Solaris Studio 环境变量(以下环境变量指定的值为不区分大小写)
1、PARALLEL
如果同时设置 PARALLEL 和 OMP_NUM_THREADS,则必须将它们设置为相同的值

2、SUNW_MP_WARN
常见错误:区域嵌套错误、显式屏障位置错误、死锁、环境变量的设置无效等等

3、 SUNW_MP_THR_IDLE
控制 OpenMP 程序中正在等待工作(空闲)或者正在屏障处等待的线程的行为
可设置为:SPIN、SLEEP、SLEEP(time s)、SLEEP(time ms)、SLEEP(time mc)
其中time设为整数,mc为us,若未设置时间单位,则默认为s

4、SUNW_MP_PROCBIND

5、SUNW_MP_MAX_POOL_THREADS
指定 OpenMP 辅助线程池的最大大小
OpenMP 辅助线程是 OpenMP 运行时库创建的用于在并行区域上运行的那些线程
辅助线程池不包含主线程和由用户程序显式创建的任何线程
如果将此环境变量设置为零,则 OpenMP 辅助线程池将为0,并且将由主线程执行所有并行区域,缺省值为1023

6、SUNW_MP_MAX_NESTED_LEVELS
设置嵌套活动并行区域的最大数量,缺省值为4

7、STACKSIZE
设置每个 OpenMP 辅助线程的堆栈大小
可选后缀 B、K、M 或 G(分别表示字节、千字节、兆字节或千兆字节)的数值,缺省时默认为K
如果未设置,则对于 32 位应用程序,缺省 OpenMP 辅助线程堆栈大小为 4 MB;对于 64 位应用程序,缺省值为 8 MB

8、SUNW_MP_GUIDED_WEIGHT
设置加权因子,该因子用于确定使用 guided 调度的循环中的块大小
该值应为正浮点数,并且应用于程序中所有使用 guided 调度的循环
如果未设置,则缺省加权因子为 2.0

9、SUNW_MP_WAIT_POLICY
允许更精确地控制程序中等待工作(空闲)、在屏障处等待或等待任务完成的 OpenMP 线程的行为
在这些等待类型中,每一类型的行为都有三种可能:旋转片刻、让出处理器片刻或休眠直至被唤醒

三、嵌套并行操作
1、OMP_NESTED
可通过设置 OMP_NESTED 环境变量来启用或禁用嵌套并行操作。缺省情况下,禁用嵌套并行操作
以下代码进行三级嵌套:

#include <omp.h>
#include <stdio.h>
void report_num_threads(int level)
{
   
    #pragma omp single
    {
   
        printf("Level %d: number of threads in the team = %d\n",
                  level, omp_get_num_threads());
    }
 }
int main()
{
   
    omp_set_dynamic(0);
    #pragma omp parallel num_threads(2)
    {
   
        report_num_threads(1);
        #pragma omp parallel num_threads(2)
        {
   
            report_num_threads(2)
MPI和OpenMP都是并行程序设计的重要工具,可以实现高效的并行计算。下面介绍两种基于MPI+OpenMP并行排序算法:归并排序和快速排序。 ## 归并排序 归并排序是种分治算法,它将待排序的数组分成两个子数组,分别排序,然后将已排序的子数组合并成个更大的有序数组。该算法的时间复杂度为O(nlogn)。 ### 并行实现 1. 每个进程读取并分配部分待排序数据。 2. 每个进程使用OpenMP并行进行归并排序。 3. 将每个进程排序后的子数组发送到Master进程。 4. Master进程使用归并操作合并每个子数组,得到最终的有序数组。 代码实现如下: ```c++ #include <stdio.h> #include <stdlib.h> #include <mpi.h> #include <omp.h> void merge(int *arr, int left, int mid, int right) { int i, j, k; int n1 = mid - left + 1; int n2 = right - mid; int L[n1], R[n2]; for (i = 0; i < n1; i++) L[i] = arr[left + i]; for (j = 0; j < n2; j++) R[j] = arr[mid + 1 + j]; i = 0; j = 0; k = left; while (i < n1 && j < n2) { if (L[i] <= R[j]) { arr[k] = L[i]; i++; } else { arr[k] = R[j]; j++; } k++; } while (i < n1) { arr[k] = L[i]; i++; k++; } while (j < n2) { arr[k] = R[j]; j++; k++; } } void mergeSort(int *arr, int left, int right) { if (left < right) { int mid = left + (right - left) / 2; #pragma omp parallel sections { #pragma omp section { mergeSort(arr, left, mid); } #pragma omp section { mergeSort(arr, mid + 1, right); } } merge(arr, left, mid, right); } } int main(int argc, char **argv) { int *data = NULL; int *sub_data = NULL; int *sub_sorted_data = NULL; int n = 1000000; int i, j, k, p, rank, size; double start, end; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); sub_data = (int *)malloc(n / size * sizeof(int)); sub_sorted_data = (int *)malloc(n / size * sizeof(int)); if (rank == 0) { data = (int *)malloc(n * sizeof(int)); for (i = 0; i < n; i++) { data[i] = rand() % n; } } start = MPI_Wtime(); MPI_Scatter(data, n / size, MPI_INT, sub_data, n / size, MPI_INT, 0, MPI_COMM_WORLD); mergeSort(sub_data, 0, n / size - 1); MPI_Gather(sub_data, n / size, MPI_INT, data, n / size, MPI_INT, 0, MPI_COMM_WORLD); if (rank == 0) { int *temp = (int *)malloc(n * sizeof(int)); for (i = 0; i < size; i++) { for (j = 0; j < n / size; j++) { temp[i * n / size + j] = data[i + j * size]; } } mergeSort(temp, 0, n - 1); free(temp); } end = MPI_Wtime(); if (rank == 0) { printf("Time: %lf seconds\n", end - start); } MPI_Finalize(); free(data); free(sub_data); free(sub_sorted_data); return 0; } ``` ## 快速排序 快速排序是种分治算法,它通过选择个基准元素,将数组分成两个子数组,其中个子数组中的元素都小于基准元素,另个子数组中的元素都大于基准元素,然后递归地排序子数组。该算法的时间复杂度为O(nlogn)。 ### 并行实现 1. 每个进程读取并分配部分待排序数据。 2. 每个进程使用OpenMP并行进行快速排序。 3. 将每个进程排序后的子数组发送到Master进程。 4. Master进程使用归并操作合并每个子数组,得到最终的有序数组。 代码实现如下: ```c++ #include <stdio.h> #include <stdlib.h> #include <mpi.h> #include <omp.h> void swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; } int partition(int *arr, int low, int high) { int pivot = arr[high]; int i = low - 1; int j; #pragma omp parallel for for (j = low; j <= high - 1; j++) { if (arr[j] < pivot) { i++; swap(&arr[i], &arr[j]); } } swap(&arr[i + 1], &arr[high]); return i + 1; } void quickSort(int *arr, int low, int high) { if (low < high) { int pi = partition(arr, low, high); #pragma omp parallel sections { #pragma omp section { quickSort(arr, low, pi - 1); } #pragma omp section { quickSort(arr, pi + 1, high); } } } } int main(int argc, char **argv) { int *data = NULL; int *sub_data = NULL; int *sub_sorted_data = NULL; int n = 1000000; int i, j, k, p, rank, size; double start, end; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); sub_data = (int *)malloc(n / size * sizeof(int)); sub_sorted_data = (int *)malloc(n / size * sizeof(int)); if (rank == 0) { data = (int *)malloc(n * sizeof(int)); for (i = 0; i < n; i++) { data[i] = rand() % n; } } start = MPI_Wtime(); MPI_Scatter(data, n / size, MPI_INT, sub_data, n / size, MPI_INT, 0, MPI_COMM_WORLD); quickSort(sub_data, 0, n / size - 1); MPI_Gather(sub_data, n / size, MPI_INT, data, n / size, MPI_INT, 0, MPI_COMM_WORLD); if (rank == 0) { int *temp = (int *)malloc(n * sizeof(int)); for (i = 0; i < size; i++) { for (j = 0; j < n / size; j++) { temp[i * n / size + j] = data[i + j * size]; } } quickSort(temp, 0, n - 1); free(temp); } end = MPI_Wtime(); if (rank == 0) { printf("Time: %lf seconds\n", end - start); } MPI_Finalize(); free(data); free(sub_data); free(sub_sorted_data); return 0; } ``` 以上两种算法都可以通过MPI+OpenMP实现并行排序,提高了算法的效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值