Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Thread Sanitizer link error

vikramb
Beginner
695 Views

Hello,

 

I am using Intel IFX 2024.2 compiler on Linux. I am trying to build my executable and dynamic libraries (on Linux) with thread sanitizer instrumented to detect data races. I am using '-fsanitize=thread' flags for both compiling as well as linking. However when I attempt to build any shared library I get linking errors like this:

 

" ... libclang_rt.tsan.a(tsan_interceptors_posix.cpp.o): relocation R_X86_64_TPOFF32 against `_ZL10pglob_copy' can not be used when making a shared object; recompile with -fPIC"

" ... libclang_rt.tsan.a(tsan_rtl.cpp.o): relocation R_X86_64_TPOFF32 against hidden symbol `_ZN6__tsan22cur_thread_placeholderE' can not be used when making a shared object"

" ... libclang_rt.tsan.a(tsan_preinit.cpp.o): .preinit_array section is not allowed in DSO"

"ld: failed to set dynamic section sizes: Nonrepresentable section on output"

 

All my libraries have the '-fPIC' compile flag. So I think the issue is with the TSAN runtime library included with the compiler. How can can I avoid these errors?

0 Kudos
5 Replies
vikramb
Beginner
694 Views

If there is a way to link against the shared version of the library (libclang_rt.tsan.so) will this problem go away?

0 Kudos
vikramb
Beginner
573 Views

Here's a minimal example (a translation of C++ example from Intel) to reproduce the error. When attempting to compile into library using the following command

ifx -shared -fPIC -fsanitize=thread -o libmergesort.so mergeSortMod.f90

I get the following errors:

" ... libclang_rt.tsan.a(tsan_interceptors_posix.cpp.o): relocation R_X86_64_TPOFF32 against `_ZL10pglob_copy' can not be used when making a shared object; recompile with -fPIC"
" ... libclang_rt.tsan.a(tsan_rtl.cpp.o): relocation R_X86_64_TPOFF32 against hidden symbol `_ZN6__tsan22cur_thread_placeholderE' can not be used when making a shared object"
"... libclang_rt.tsan.a(tsan_preinit.cpp.o): .preinit_array section is not allowed in DSO"
"ld: failed to set dynamic section sizes: Nonrepresentable section on output"
! Fortran Implementation of Intel C++ Code Example
module MergeSortModule
  use omp_lib
  implicit none
  integer, parameter :: task_threshold = 5000  ! Threshold for creating OpenMP tasks
  integer :: my_counter = 0  ! Counter to track function calls
contains

  ! Description: Initializes the array and shuffles the elements.
  subroutine InitializeArray(a, n)
    integer, intent(inout) :: a(:)
    integer, intent(in) :: n
    integer :: i, tmp, j

    ! Initialize the array
    do i = 1, n
      a(i) = i - 1
    end do

    print *, "Shuffling the array"

    ! Shuffle the array (Fisher-Yates Shuffle Algorithm)
    call random_seed()
    do i = n, 2, -1
      call random_number(tmp)
      j = floor(tmp * real(i)) + 1
      tmp = a(i)
      a(i) = a(j)
      a(j) = tmp
    end do
  end subroutine InitializeArray

  ! Description: Checks if the array is correctly sorted
  function CheckArray(a, n) result(error_flag)
    integer, intent(in) :: a(:)
    integer, intent(in) :: n
    integer :: i, error_flag

    error_flag = 0  ! Assume no errors

    do i = 1, n - 1
      if (a(i) >= a(i + 1) .or. a(i) /= (i - 1)) then
        print *, "Sort failed at location", i, ", a(i)=", a(i), " a(i+1)=", a(i + 1)
        error_flag = 1
        return
      end if
    end do
  end function CheckArray

  ! Description: Merges two sublists of the array
  subroutine Merge(a, tmp_a, first, middle, last)
    integer, intent(inout) :: a(:), tmp_a(:)
    integer, intent(in) :: first, middle, last
    integer :: p1, p2, p, i

    p1 = first
    p2 = middle
    p = first

    ! Merge two portions of the array into the temporary array
    do while (p <= last)
      if (p1 < middle .and. (p2 > last .or. a(p1) < a(p2))) then
        tmp_a(p) = a(p1)
        p1 = p1 + 1
      else
        tmp_a(p) = a(p2)
        p2 = p2 + 1
      end if
      p = p + 1
    end do

    ! Copy the sorted portion back to the original array
    do i = first, last
      a(i) = tmp_a(i)
    end do
  end subroutine Merge

  ! Description: Recursive MergeSort algorithm
  recursive subroutine MergeSort(a, tmp_a, first, last)
    integer, intent(inout) :: a(:), tmp_a(:)
    integer, intent(in) :: first, last
    integer :: middle

    if (first < last) then
      middle = (first + last + 1) / 2
      call MergeSort(a, tmp_a, first, middle - 1)
      call MergeSort(a, tmp_a, middle, last)
      call Merge(a, tmp_a, first, middle, last)
    end if
  end subroutine MergeSort

  ! Description: OpenMP Task-based version of MergeSort
  recursive subroutine MergeSortOpenMP(a, tmp_a, first, last)
    integer, intent(inout) :: a(:), tmp_a(:)
    integer, intent(in) :: first, last
    integer :: middle

    if (first < last) then
      middle = (first + last + 1) / 2

      if (last - first < task_threshold) then
        call MergeSort(a, tmp_a, first, middle - 1)
        call MergeSort(a, tmp_a, middle, last)
      else
!$omp task
        call MergeSortOpenMP(a, tmp_a, first, middle - 1)
!$omp task
        call MergeSortOpenMP(a, tmp_a, middle, last)
!$omp taskwait
      end if

      call Merge(a, tmp_a, first, middle, last)
      my_counter = my_counter + 1
    end if
  end subroutine MergeSortOpenMP

end module MergeSortModule

 

0 Kudos
vikramb
Beginner
643 Views

There is small error in the call to random_number subroutine in the code snippet above. It needs a real argument 'rtmp' instead of integer 'tmp'. This needs to be declared as well.

0 Kudos
vikramb
Beginner
573 Views

The code snippet to reproduce the errors is below.
 

The command I tried is

ifx -shared -fPIC -fsanitize=thread -o libmergesort.so mergeSortMod.f90
! Modern Fortran Implementation of the Given C++ Code
module MergeSortModule
  use omp_lib
  implicit none
  integer, parameter :: task_threshold = 5000  ! Threshold for creating OpenMP tasks
  integer :: my_counter = 0  ! Counter to track function calls
contains

  ! Description: Initializes the array and shuffles the elements.
  subroutine InitializeArray(a, n)
    integer, intent(inout) :: a(:)
    integer, intent(in) :: n
    integer :: i, tmp, j
	real :: rtmp

    ! Initialize the array
    do i = 1, n
      a(i) = i - 1
    end do

    print *, "Shuffling the array"

    ! Shuffle the array (Fisher-Yates Shuffle Algorithm)
    call random_seed()
    do i = n, 2, -1
      call random_number(rtmp)
      j = floor(rtmp * real(i)) + 1
      tmp = a(i)
      a(i) = a(j)
      a(j) = tmp
    end do
  end subroutine InitializeArray

  ! Description: Checks if the array is correctly sorted
  function CheckArray(a, n) result(error_flag)
    integer, intent(in) :: a(:)
    integer, intent(in) :: n
    integer :: i, error_flag

    error_flag = 0  ! Assume no errors

    do i = 1, n - 1
      if (a(i) >= a(i + 1) .or. a(i) /= (i - 1)) then
        print *, "Sort failed at location", i, ", a(i)=", a(i), " a(i+1)=", a(i + 1)
        error_flag = 1
        return
      end if
    end do
  end function CheckArray

  ! Description: Merges two sublists of the array
  subroutine Merge(a, tmp_a, first, middle, last)
    integer, intent(inout) :: a(:), tmp_a(:)
    integer, intent(in) :: first, middle, last
    integer :: p1, p2, p, i

    p1 = first
    p2 = middle
    p = first

    ! Merge two portions of the array into the temporary array
    do while (p <= last)
      if (p1 < middle .and. (p2 > last .or. a(p1) < a(p2))) then
        tmp_a(p) = a(p1)
        p1 = p1 + 1
      else
        tmp_a(p) = a(p2)
        p2 = p2 + 1
      end if
      p = p + 1
    end do

    ! Copy the sorted portion back to the original array
    do i = first, last
      a(i) = tmp_a(i)
    end do
  end subroutine Merge

  ! Description: Recursive MergeSort algorithm
  recursive subroutine MergeSort(a, tmp_a, first, last)
    integer, intent(inout) :: a(:), tmp_a(:)
    integer, intent(in) :: first, last
    integer :: middle

    if (first < last) then
      middle = (first + last + 1) / 2
      call MergeSort(a, tmp_a, first, middle - 1)
      call MergeSort(a, tmp_a, middle, last)
      call Merge(a, tmp_a, first, middle, last)
    end if
  end subroutine MergeSort

  ! Description: OpenMP Task-based version of MergeSort
  recursive subroutine MergeSortOpenMP(a, tmp_a, first, last)
    integer, intent(inout) :: a(:), tmp_a(:)
    integer, intent(in) :: first, last
    integer :: middle

    if (first < last) then
      middle = (first + last + 1) / 2

      if (last - first < task_threshold) then
        call MergeSort(a, tmp_a, first, middle - 1)
        call MergeSort(a, tmp_a, middle, last)
      else
!$omp task
        call MergeSortOpenMP(a, tmp_a, first, middle - 1)
!$omp task
        call MergeSortOpenMP(a, tmp_a, middle, last)
!$omp taskwait
      end if

      call Merge(a, tmp_a, first, middle, last)
      my_counter = my_counter + 1
    end if
  end subroutine MergeSortOpenMP

end module MergeSortModule

 

0 Kudos
vikramb
Beginner
599 Views

Somehow all previous attempts to include code inside have not worked. A minimal example source file is attached. The command I used is 'ifx -shared -fPIC -fsanitize=thread -o libmergesort.so MergeSortModule.f90'.

0 Kudos
Reply