JavaScript is required to for searching.
跳过导航链接
退出打印视图
Oracle Solaris Studio 12.3:线程分析器用户指南     Oracle Solaris Studio 12.3 Information Library (简体中文)
search filter icon
search icon

文档信息

前言

1.  什么是线程分析器?它有什么作用?

2.  数据争用教程

2.1 数据争用教程源文件

2.1.1 获取数据争用教程源文件

2.1.2 prime_omp.c 的源代码

2.1.3 prime_pthr.c 的源代码

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

2.2 如何使用线程分析器查找数据争用

2.2.1 检测代码

2.2.1.1 检测源代码

2.2.1.2 检测二进制代码

2.2.2 创建数据争用检测实验

2.2.3 检查数据争用检测实验

2.2.3.1 使用线程分析器查看数据争用实验

2.2.3.2 使用 er_print 查看数据争用实验

2.3 了解实验结果

2.3.1 prime_omp.c 中的数据争用

2.3.2 prime_pthr.c 中的数据争用

2.3.3 数据争用的调用堆栈跟踪

2.4 诊断数据争用的原因

2.4.1 检查数据争用是否为误报

2.4.2 检查数据争用是否为良性

2.4.3 修复错误而不是修复数据争用

2.4.3.1 修复 prime_omp.c 中的错误

2.4.3.2 修复 prime_pthr.c 中的错误

2.5 误报

2.5.1 用户定义的同步

2.5.2 由不同线程回收的内存

2.6 良性数据争用

2.6.1 用于查找质数的程序

2.6.2 用于检验数组值类型的程序

2.6.3 使用双检锁的程序

3.  死锁教程

A.  线程分析器可识别的 API

B.  有用提示

2.1 数据争用教程源文件

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

2.1.1 获取数据争用教程源文件

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

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

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

2.1.2 prime_omp.c 的源代码

prime_omp.c 的源代码如下所示:

  1  /*
  2   * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All Rights Reserved.
  3   * @(#)prime_omp.c 1.3 (Oracle) 10/03/26
  4   */
  5
  6  #include <stdio.h>
  7  #include <math.h>
  8  #include <omp.h>
  9
 10  #define THREADS 4
 11  #define N 10000
 12
 13  int primes[N];
 14  int pflag[N];
 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  int main(int argn, char **argv)
 34  {
 35      int i;
 36      int total = 0;
 37
 38  #ifdef _OPENMP
 39      omp_set_dynamic(0);
 40      omp_set_num_threads(THREADS);
 41  #endif
 42
 43      for (i = 0; i < N; i++) {
 44          pflag[i] = 1;
 45      }
 46
 47      #pragma omp parallel for
 48      for (i = 2; i < N; i++) {
 49          if ( is_prime(i) ) {
 50              primes[total] = i;
 51              total++;
 52          }
 53      }
 54
 55      printf("Number of prime numbers between 2 and %d: %d\n",
 56             N, total);
 57
 58      return 0;
 59  }

2.1.3 prime_pthr.c 的源代码

prime_pthr.c 的源代码如下所示:

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

2.1.3.1 数据争用在 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

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

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