Oracle® Developer Studio 12.5:线程分析器用户指南

退出打印视图

更新时间: 2016 年 6 月
 
 

数据争用教程源文件

本教程所依赖的两个程序都存在数据争用:

  • 第一个程序查找质数。该程序是用 C 编写的,并使用 OpenMP 指令进行了并行化。该源文件称为 prime_omp.c

  • 第二个程序也查找质数,并且也是用 C 编写的。但是,它使用 POSIX 线程(而不是 OpenMP 指令)进行并行化。该源文件称为 prime_pthr.c

获取数据争用教程源文件

您可以从 Oracle Developer Studio 开发者门户的下载区域中下载本教程所用的源文件。

在下载并解压缩样例文件之后,您可以在 OracleDeveloperStudio12.5-Samples/ThreadAnalyzer 目录中找到样例。这些样例位于 prime_ompprime_pthr 子目录中。每个样例目录都包含 MakefileDEMO 说明文件,但是本教程并不遵循这些说明,也不使用 Makefile。本教程将逐步指导您执行命令。

为跟随本教程学习,您可以将 prime_omp.cprime_pthr.c 文件从样例目录复制到其他目录,也可以创建自己的文件并从下面列出的代码内容中复制代码。

prime_omp.c 的源代码

本节列出了 prime_omp.c 的源代码,如下所示:

     1	/* 
     2	 * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All Rights Reserved.
     3	 */
     4	
     5	#include <stdio.h>
     6	#include <math.h>
     7	#include <omp.h>
     8	
     9	#define THREADS 4
    10	#define N 10000
    11	
    12	int primes[N];
    13	int pflag[N];
    14	
    15	int is_prime(int v)
    16	{
    17	    int i;
    18	    int bound = floor(sqrt(v)) + 1;
    19	    
    20	    for (i = 2; i < bound; i++) {
    21	        /* no need to check against known composites */ 
    22	        if (!pflag[i]) 
    23	            continue;
    24	        if (v % i == 0) { 
    25	            pflag[v] = 0;
    26	            return 0;
    27	        }
    28	    }
    29	    return (v > 1); 
    30	}
    31	
    32	int main(int argn, char **argv)
    33	{
    34	    int i;
    35	    int total = 0;
    36	
    37	#ifdef _OPENMP
    38	    omp_set_dynamic(0);
    39	    omp_set_num_threads(THREADS);
    40	#endif
    41	
    42	    for (i = 0; i < N; i++) {
    43	        pflag[i] = 1; 
    44	    }
    45	    
    46	    #pragma omp parallel for
    47	    for (i = 2; i < N; i++) {
    48	        if ( is_prime(i) ) {
    49	            primes[total] = i;
    50	            total++;
    51	        }
    52	    }
    53	
    54	    printf("Number of prime numbers between 2 and %d: %d\n",
    55	           N, total);
    56	
    57	    return 0;
    58	}

prime_pthr.c 的源代码

本节列出了 prime_pthr.c 的源代码,如下所示:

     1	/* 
     2	 * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All Rights Reserved.
     3	 */
     4	
     5	#include <stdio.h>
     6	#include <math.h>
     7	#include <pthread.h>
     8	
     9	#define THREADS 4
    10	#define N 10000
    11	
    12	int primes[N];
    13	int pflag[N];
    14	int total = 0;
    15	
    16	int is_prime(int v)
    17	{
    18	    int i;
    19	    int bound = floor(sqrt(v)) + 1;
    20	
    21	    for (i = 2; i < bound; i++) {
    22	        /* no need to check against known composites */ 
    23	        if (!pflag[i])
    24	            continue;
    25	        if (v % i == 0) {
    26	            pflag[v] = 0;
    27	            return 0;
    28	        }
    29	    }
    30	    return (v > 1); 
    31	}
    32	
    33	void * work(void *arg)
    34	{
    35	    int start;
    36	    int end;
    37	    int i;
    38	
    39	    start = (N/THREADS) * (*(int *)arg);
    40	    end = start + N/THREADS;
    41	    for (i = start; i < end; i++) {
    42	        if ( is_prime(i) ) {
    43	            primes[total] = i;
    44	            total++;        
    45	        }
    46	    }
    47	    return NULL;
    48	}
    49	
    50	int main(int argn, char **argv)
    51	{
    52	    int i;
    53	    pthread_t tids[THREADS-1];
    54	
    55	    for (i = 0; i < N; i++) {
    56	        pflag[i] = 1; 
    57	    }
    58	
    59	    for (i = 0; i < THREADS-1; i++) {
    60	        pthread_create(&tids[i], NULL, work, (void *)&i);
    61	    }
    62	
    63	    i = THREADS-1;
    64	    work((void *)&i);
    65	        
    66	    for (i = 0; i < THREADS-1; i++) {
    67	        pthread_join(tids[i], NULL);
    68	    }
    69	
    70	    printf("Number of prime numbers between 2 and %d: %d\n",
    71	           N, total);
    72	
    73	    return 0;
    74	}

数据争用在 prime_omp.cprime_pthr.c 中的效果

当代码包含争用情况时,内存访问的顺序是不确定的,因此每次运行的计算结果会不同。prime_ompprime_pthr 程序中的正确答案为 1229。

通过编译并运行示例可以看出,由于代码中存在数据争用,执行 prime_ompprime_pthr 时都会产生不正确且不一致的结果。

在下面的示例中,在提示符下键入命令以编译并运行 prime_omp 程序:

% cc -xopenmp=noopt -o prime_omp prime_omp.c -lm
%
% ./prime_omp
Number of prime numbers between 2 and 10000: 1229
% ./prime_omp
Number of prime numbers between 2 and 10000: 1228
% ./prime_omp
Number of prime numbers between 2 and 10000: 1180

在下面的示例中,在提示符处键入命令以编译并运行 prime_pthr 程序:

% cc -mt -o prime_pthr prime_pthr.c -lm
%
% ./prime_pthr
Number of prime numbers between 2 and 10000: 1140
% ./prime_pthr
Number of prime numbers between 2 and 10000: 1122
% ./prime_pthr
Number of prime numbers between 2 and 10000: 1141

请注意每个程序的三次运行结果的不一致性。可能需要运行这些程序三次以上才能看到不一致的结果。

接下来将会检测代码并创建实验,以便可以找出发生数据争用的位置。