Fix Sharing Problems

View the Correctness Report and Correctness Source windows to help you fix the reported data sharing problems. To do this:

Examine Correctness Report and Correctness Source Windows

The Correctness tool reports two problems:

  • Memory reuse problem type. This is located in the solve subroutine.
  • Data communication problem type. This is located in the SetQueen subroutine.

Unlike problems reported in serial programming, which often have a single cause, problems in parallel programming usually involve multiple code regions. For example, consider the case where three different code regions allocate, initialize, and access the same memory location - and each is located in two or more tasks. In the parallel version of the program, these allocate-initialize-access actions could occur at the same time. Thus, the multiple code regions have relationships, so the Correctness Report window shows a Focus code location and Related code locations.

To open the Visual Studio code editor to the relevant source code:

  1. In the Problems and Messages pane, double-click one of the two problems with a severity of Error ().
  2. View the source code in the Correctness Source window. This is the Focus Code Location pane. You can view the Related Code Locations or simply double-click the source code to launch the Visual Studio editor with that file opened at the same position.
  3. In each case, scroll up to locate the subroutine containing the source code:

    • The Memory reuse problem originates in the solve subroutine.
    • The Data communication problem is located in the SetQueen subroutine.

  4. Read the source comments that explain the solution to both problems.
  5. To return from a source view to the corresponding Correctness Report window, click the Correctness Report button in the result tab for that project.

Fix the Memory Reuse Sharing Problem

To fix the Memory reuse problem located in the solve subroutine, examine that subroutine's code:

! Main solver routine
subroutine solve (queens)
  implicit none
  integer, intent(inout) :: queens(:)
  integer :: i
  
  call annotate_site_begin("solve")
  do i=1,size
    call annotate_iteration_task("setQueen")
    ! try all positions in first row
    call SetQueen (queens, 1, i)
  end do
  call annotate_site_end()
end subroutine solve

The call to SetQueen is located within the parallel site. Examine the SetQueen subroutine code and you will notice that the current version of the setQueen subroutine uses the same array passed from the solve subroutine:

recursive subroutine setQueen (queens, row, col)
  implicit none
  integer, intent(inout) :: queens(:)
  integer, intent(in) :: row, col
  integer :: i
  integer, volatile :: j
  
  !In order to avoid a data race on the "queens" array create a local copy.
  !Uncomment the statements using the "lcl_queens" array and comment the 
  !statements using the "queens" array.
  !integer :: lcl_queens(ubound(queens,dim=1))
  
  ! Make copy of queens array
  !lcl_queens = queens

  do i=1,row-1
    ! vertical attacks
    !if (lcl_queens(i) == col) return
    if (queens(i) == col) return
    ! diagonal attacks
    !if (abs(lcl_queens(i)-col) == (row-i)) return
    if (abs(queens(i)-col) == (row-i)) return
    end do
    
  ! column is ok, set the queen
  !lcl_queens(row) = col
  queens(row) = col
  
  if (row == size) then
    !uncomment the following 2 lock annotations to avoid a datarace on the nrOfSolutions variable. 
    !call annotate_lock_acquire(0)
    nrOfSolutions = nrOfSolutions + 1
    !call annotate_lock_release(0)
  else
    ! try to fill next row
    do j=1,size
      !call setQueen (lcl_queens, row+1, j)
      call setQueen (queens, row+1, j)
    end do
  end if
end subroutine SetQueen

This placement causes the site code and each task to share the same array! This is called incidental or accidental data sharing:

!In order to avoid a data race on the "queens" array create a local copy.
!Uncomment the statements using the "lcl_queens" array and comment the 
!statements using the "queens" array.
!integer :: lcl_queens(ubound(queens,dim=1))
  
! Make copy of queens array
!lcl_queens = queens

Instead of sharing this queens array, each task should have its own private copy of this array. You need to comment out the lines that use the queens array and uncomment lines that use the lcl_queens array as well as the lines above that declare and assign it:

recursive subroutine setQueen (queens, row, col)
  implicit none
  integer, intent(inout) :: queens(:)
  integer, intent(in) :: row, col
  integer :: i
  integer, volatile :: j
  
  !In order to avoid a data race on the "queens" array create a local copy.
  !Uncomment the statements using the "lcl_queens" array and comment the 
  !statements using the "queens" array.
  integer :: lcl_queens(ubound(queens,dim=1))
  
  ! Make copy of queens array
  lcl_queens = queens

  do i=1,row-1
    ! vertical attacks
    if (lcl_queens(i) == col) return
    !if (queens(i) == col) return
    ! diagonal attacks
    if (abs(lcl_queens(i)-col) == (row-i)) return
    !if (abs(queens(i)-col) == (row-i)) return
    end do
    
  ! column is ok, set the queen
  lcl_queens(row) = col
  !queens(row) = col
  
  if (row == size) then
    !uncomment the following 2 lock annotations to avoid a datarace on the nrOfSolutions variable. 
    !call annotate_lock_acquire(0)
    nrOfSolutions = nrOfSolutions + 1
    !call annotate_lock_release(0)
  else
    ! try to fill next row
    do j=1,size
      call setQueen (lcl_queens, row+1, j)
      !call setQueen (queens, row+1, j)
    end do
  end if
end subroutine SetQueen

By assigning a private copy to each task using the lcl_queens array, the Memory Reuse problem will be fixed.

Fix the Data Communication Sharing Problem

To fix the Data communication problem located in the SetQueen subroutine, examine that subroutine's code:

...
  ! column is ok, set the queen
  lcl_queens(row) = col
  !queens(row) = col
  
  if (row == size) then
    !uncomment the following 2 lock annotations to avoid a datarace on the nrOfSolutions variable. 
    !call annotate_lock_acquire(0)
    nrOfSolutions = nrOfSolutions + 1
    !call annotate_lock_release(0)
  else
    ! try to fill next row
    do j=1,size
      call setQueen (lcl_queens, row+1, j)
      !call setQueen (queens, row+1, j)
    end do
  end if
end subroutine SetQueen
        

The line that increments the variable nrOfSolutions is located in the recursively called SetQueen subroutine, which is called from multiple tasks. This causes a data race, or a Data communication problem. The accesses to this data must be synchronized. You can uncomment the pair of !call annotate_lock_acquire(0) and !call annotate_lock_release(0) annotation lines.

On Windows* OS systems, you can use the following procedure to insert Intel Advisor annotations using the Visual Studio* code editor :

  1. In the Visual Studio code editor, select the range of code line(s) to be included by the annotation. For example: Select a line or a range of code
  2. Right click to display a context menu.
  3. From the context menu, select Intel Advisor XE 2013 > Annotation Wizard.
  4. From the drop-down list, select Annotate Lock.
  5. Click Next

  6. To the right of Specify annotation parameter <lock_id>, replace the placeholder <lock_id> with 0 and click Next.
  7. View the proposed modified code and click Finish.
  8. The resulting code below shows the two lock annotations inserted by the Annotation Wizard:

    Code shown after the Annotation Wizard inserts a pair of lock annotations

  9. Because you modified the source code, rebuild the sample 2_nqueens_annotated project to create a new target for the Correctness tool. For example, in Microsoft Visual Studio, click the Build menu and select Build 2_nqueens_annotated. Examine the Output window to verify that no build errors were detected.

Once you have modified your code to fix both data sharing problems:

  1. Rebuild the target.

  2. Run the Correctness tool again and verify that the problems have been fixed. That is, the only line displayed in the Problems and Messages pane is Parallel site information.

  3. If they have been fixed, run the Suitability tool again using a Release build target to check the performance implications of the modified sources.

For more complete information about compiler optimizations, see our Optimization Notice.