Changes between Version 2 and Version 3 of OpenMP-Transformation-Introduction


Ignore:
Timestamp:
12/03/21 13:51:02 (4 years ago)
Author:
wuwenhao
Comment:

Update contents for OpenMP simplification and model checking

Legend:

Unmodified
Added
Removed
Modified
  • OpenMP-Transformation-Introduction

    v2 v3  
    139139As a result, all required pairs are checked.
    140140
     141== 1.3 OpenMP Simplification ==
     142
     143=== OpenMP Simplifier ===
     144* We improve the existing OpenMP simplifier with the informations provided by the [[wiki: StaticAnalysis| Static Analysis]].
     145* Example 1: (`DRB067-restrictpointer1-orig-no.c` from [https://github.com/LLNL/dataracebench/releases/tag/v1.2.0 DataRaceBench v1.2.0])
     146{{{
     147#include <stdlib.h>
     148typedef double real8;
     149
     150void foo(real8 * restrict newSxx, real8 * restrict newSyy, int length)
     151{
     152  int i;
     153
     154#pragma omp parallel for private (i) firstprivate (length)
     155  for (i = 0; i <= length - 1; i += 1) {
     156    newSxx[i] = 0.0;
     157    newSyy[i] = 0.0;
     158  }
     159}
     160
     161int main()
     162{
     163  int length=10;
     164  real8* newSxx = malloc (length* sizeof (real8));
     165  real8* newSyy = malloc (length* sizeof (real8));
     166
     167  foo(newSxx, newSyy, length);
     168
     169  free (newSxx);
     170  free (newSyy);
     171  return 0;
     172}
     173}}}
     174  * The OpenMP simplifier analyzes the parallel region with points-to informations about the two pointer argument `newSxx` and `newSyy` from static analysis.
     175  * The OpenMP simplifier can determine that no data race will happen in the parallel region as long as no array out-of-bound error happens in it.
     176  * The OpenMP simplifier sequentializes the program which will be checked by CIVL.  Any possible array out-of-bound error will be caught by CIVL.
     177
     178* Example 2 : ( `DRB014-outofbounds-orig-yes.c` from  [https://github.com/LLNL/dataracebench/releases/tag/v1.2.0 DataRaceBench v1.2.0] )
     179{{{
     180#include <stdio.h>
     181int main(int argc, char* argv[])
     182{
     183  int i,j;
     184  int n=10, m=10;
     185  double b[n][m];
     186#pragma omp parallel for private(j)
     187  for (i=1;i<n;i++)
     188    for (j=0;j<m;j++) // Note there will be out of bound access                                                               
     189      b[i][j]=b[i][j-1];
     190
     191  printf ("b[50][50]=%f\n",b[50][50]);
     192
     193  return 0;
     194}
     195}}}
     196  * OpenMP Simplifier proves that `b[i][j]` and `b[i][j-1]` that accessed by different threads which hold different values of `i` will have no data race as long as no array out-of-bound error happens.
     197  * OpenMP Simplifier sequentializes the OpenMP program while the verification condition for array out-of-bound freedom will be checked by CIVL by default.
     198  * The CIVL back-end runs the sequentialized program and detects the array out-of-bound access.
     199
     200
     201=== Notes ===
     202* The OpenMP simplification transformation shall use pointer alias analysis
     203 * The simplifier currently cannot detect data race caused by out-of-bound access on multiple dimensional arrays. The simplification transformer incorrectly sequentializes the example below without realizing that it can be sequentialized if and only if **no 'logical' out-of-bound happens during the execution**. A possible fix for this issue could be sequentializing the example with inserted assertions for ensuring the absence of 'logical' out-of-bound error.
     204
     205  e.g.,
     206{{{
     207  int a[10][5];
     208#pragma omp parallel for
     209  for (int i = 0; i < 5; i++)
     210    for (int j = 1; j < 10; j++)
     211      a[i][j] = a[i][j-1];
     212      //a[0][4] and a[1][-1] refer to the same element
     213}}}
     214
     215== 1.4 Model Checking OpenMP Programs ==
     216=== The Current Approach For Model Checking OpenMP Programs ===
     217* Example:
     218{{{
     219#include <omp.h>
     220int main()
     221{
     222  int a[10],i;
     223
     224#pragma omp parallel for
     225  for(i=0; i<10; i++)
     226    {
     227      int c;
     228
     229      c = i % 2;
     230      a[i + c] = 0;
     231    }
     232}
     233}}}
     234  * OpenMP Simplifier cannot prove data-race freedom for this program.
     235  * OpenMP2CIVL Transformer will transform this program to a equivalent CIVL-C program for model checking. Here is the code snippet for the CIVL-C program after transformation:
     236  {{{
     237int main() {
     238  int  a[10];
     239  {
     240    {
     241      int _elab_i = 0;
     242      for (; _elab_i < _omp_num_threads; _elab_i = _elab_i + 1)
     243        ;
     244    }
     245    int $sef$0 = $choose_int(_omp_num_threads);
     246    int _omp_nthreads = 1 + $sef$0;
     247    $range _omp_thread_range = 0 .. _omp_nthreads - 1;
     248    $domain(1) _omp_dom = ($domain){_omp_thread_range};
     249    $omp_gteam _omp_gteam = $omp_gteam_create($here, _omp_nthreads);
     250    $omp_gshared _omp_a_gshared = $omp_gshared_create(_omp_gteam, &(a));
     251    $parfor (int _omp_tid: _omp_dom) {
     252      $omp_team _omp_team = $omp_team_create($here, _omp_gteam, _omp_tid);
     253      int  _omp_a_local[10];
     254      int  _omp_a_status[10];
     255      $omp_shared _omp_a_shared = $omp_shared_create(_omp_team, _omp_a_gshared, &(_omp_a_local), &(_omp_a_status));
     256      {
     257        $range _omp_r1 = 1 .. 10 - 1 # 1;
     258        $domain(1) _omp_loop_domain = ($domain){_omp_r1};
     259        $domain $sef$1 = $omp_arrive_loop(_omp_team, 0, ($domain)_omp_loop_domain, 2);
     260        $domain(1) _omp_my_iters = ($domain(1))$sef$1;
     261        $for (int _omp_i_private: _omp_my_iters) {
     262          int c;
     263          c = _omp_i_private % 2;
     264          int _omp_write0;
     265          _omp_write0 = 0;
     266          $omp_write(_omp_a_shared, &(_omp_a_local[c]), &(_omp_write0));
     267        }
     268      }
     269      $omp_barrier_and_flush(_omp_team);
     270      $omp_shared_destroy(_omp_a_shared);
     271      $omp_team_destroy(_omp_team);
     272    }
     273    $omp_gshared_destroy(_omp_a_gshared);
     274    $omp_gteam_destroy(_omp_gteam);
     275  }
     276}
     277  }}}
     278  * CIVL reports PROVABLE errors:
     279  {{{
     280Thread 1 can not safely write to memory location &<d5>a[0], because thread 0 has
     281written to that memory location and hasn't flushed yet.
     282
     283Violation 0 encountered at depth 64:
     284CIVL execution violation in p2 (kind: ASSERTION_VIOLATION, certainty: PROVEABLE)
     285at OpenMPTransformer "_omp_a_shared, &(_om" inserted by OpenMPTransformer.a_sharedWriteCall before civlc.cvh:105.14-20 "$malloc"
     286Assertion: false
     287 -> false
     288. . .
     289Call stacks:
     290process 0:
     291  main at OpenMPTransformer "$parfor (int _omp_ti" inserted by OpenMPTransformer.parallelPragma before civlc.cvh:105.14-20 "$malloc"
     292process 1:
     293  $barrier_exit at concurrency.cvl:58.2-6 "$when" called from
     294  $barrier_call at concurrency.cvl:63.2-14 "$barrier_exit" called from
     295  $omp_barrier_and_flush at civl-omp.cvl:322.2-14 "$barrier_call" called from
     296  _par_proc0 at OpenMPTransformer "_omp_team" inserted by OpenMPTransformer.barrierAndFlushCall before civlc.cvh:105.14-20 "$malloc"
     297process 2:
     298  $omp_write at civl-omp.cvl:247.4-10 "$assert" called from
     299  _par_proc0 at OpenMPTransformer "_omp_a_shared, &(_om" inserted by OpenMPTransformer.a_sharedWriteCall before civlc.cvh:105.14-20 "$malloc"
     300process 3:
     301  $omp_arrive_loop at civl-omp.cvl:405.2-8 "$atomic" called from
     302  _par_proc0 at OpenMPTransformer "_omp_team, 0, ($doma" inserted by OpenMPTransformer.myItersDeclaration before civlc.cvh:105.14-20 "$malloc"
     303
     304Logging new entry 0, writing trace to CIVLREP/testOmp5_0.trace
     305Terminating search after finding 1 violation.
     306
     307  }}}
     308
     309=== The New Approach for Model Checking OpenMP programs ===
     310* Using CIVL's new infrastructure that captures reads / writes at runtime
     311* If the OpenMP Simplifier fails to sequentialize a program,  transform the OpenMP program to the following form for model checking:
     312{{{
     313$mem writes[nthreads], reads[nthreads];
     314$parfor (int tid:0..nthreads-1) {
     315  $write_set_push();
     316  $read_set_push();
     317  block1;
     318  // barrier
     319  writes[tid] = $write_set_pop();                                                                                                               
     320  reads[tid] = $read_set_pop();
     321  // check for dataraces (collective operation)                                                                           
     322  $write_set_push();
     323  $read_set_push();
     324  // barrier                                                                                                                 
     325  stmt2;
     326  // barrier
     327  writes[tid] = $write_set_pop();                                                                                                               
     328  reads[tid] = $read_set_pop();                                                                                                                 
     329  // check for dataraces (collective operation)
     330}
     331}}}
     332* Functions for managing `$mem` objects can be found in `mem.cvh`
     333
     334
    141335----
    142336[https://vsl.cis.udel.edu/trac/civl/wiki/Next-GenOpenMPTransformation Back: Index]