Intel® Moderncode for Parallel Architectures
Support for developing parallel programming applications on Intel® Architecture.
1696 Discussions

synchronization Problem with threading in FORTRAN 95

hrushi_397
Beginner
1,347 Views

Hi all,

I am recently facing a problem with threading. My code runs perfectly well when single thread is used. However, when new threads are opened it goes into infinite loop. When I used the Intel Thread checker, it doesnot give any diagnostics at all. It oscillates between different subroutines.

Once when I ran the thread checker, it said that there is a mismatch between subroutine in ehich i have done parallel programming and between end of program. However, my parallel code ends in the subroutine itself. Then how can it go & interact with end of the program. Please somebody help me out.

Thank you.

0 Kudos
13 Replies
jimdempseyatthecove
Honored Contributor III
1,347 Views

Could you post the code?

Jim Dempsey

0 Kudos
hrushi_397
Beginner
1,347 Views

Hi Jim,

Sorry but I cannot post the code because its too large to post(more than 25000 lines...). It runs perfectly fine on single thread, but it goes into infinite loop when threaded. The threadchecker doesnot show any diagnosys so we can assume safely that no data-race takes place. Then what do you think may be the reason for this abnormal behaviour?

Thank you.

Hrushi

0 Kudos
Thomas_W_Intel
Employee
1,347 Views

Hrushi,

When you say that it "goes into an infinite loop", I assume that your program simply never finishes, right? If ThreadChecker fails to tell you why this happens, have you tried to attach a debugger? Is your program in a dead-lock or is it really in a loop? If the latter is true, is it possible to trace the variables that would end the loop?

Kind regards

Thomas

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,347 Views

Hrushi,

The Thread Checker:

Does not tell you the program is without error.
Does tell you it has detected and error.

Thismeans undetected errors can still exist in your code.
And this means you can write perfectly valid bad code.

And it also means the code the could could be written correctly with a deadlock (unintended deadlock).

Most debuggers permit you to attach to a running application and cause it to immediately enter a breakpoint. From there you can identyfy the execution location of each thread. From those locations you can (hopefully) determine the cause of the deadlock. Often is the case the debugger breakpoint can cause a cessation of the deadlock. Hopefully it will not.

Most deadlocks occure when you have multiple threads accessing shared variables under the assumption that each thread has exclusive use to the variables.

Unlike C/C++, and depending on compiler options, many items declared in the scope of a subroutine may implicitlyinstantiate a static structure (as opposed to C/C++ implicitly instantiating a Stack structure).

subroutine foo
real :: a, b(3)

"a" will most often be stack local
"b(3)" most often with be static (SAVE in FORTRAN-Speak)

subroutine foo
real, automatic :: a, b(3)

or

subroutine foo
real :: a
real, automatic :: b(3)

will force both to be stack local

Yes, you could fix the problem with option switches.

Jim Dempsey

0 Kudos
hrushi_397
Beginner
1,347 Views

Hi Thomas,

Thank you for your reply.

Yes I have tried the debugger in Visual Studio 2005. It says that some of the variables are having undefined address. That is why one of the variable value becomes zero which is leading to an infinte loop. When I tried it on thread checker, it showed me that one thread out of two is in that infinite loop, while the other thread has not even started.

Now why is it so happening? Why is it that the pointer points to an undefined address when it shoud point at a definite address? Do you have any idea?

Regards,

Hrushi

0 Kudos
hrushi_397
Beginner
1,347 Views

Thank you a lot Jim,

Your notes are really detailed. But they didnot help me to solve a problem.

You must have read my previous reply that pointers in my program are pointing to 'undefined addresses' when they are put on multiple threads. First we thought of it as sync. problem, now however we have come to know that its problem with thread itself.

Do you have any idea why is this happening?

Regards,

Hrushi

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,347 Views

Hrushi,

How is the pointer variable declared? The one that is showing the 'undefined address'. Include informnation as to the placement of the declaration statement (e.g. is this in a Module?, is it a subroutine local variable, ...). And if in subroutine, is the subroutine called from within multiple thread session (as opposed to the subroutine starting a multiple thread session).

Also, is the value of the pointer 0x00000000 or does it point somewhere else (to an invalid address).

Jim

0 Kudos
hrushi_397
Beginner
1,347 Views

Hi Jim,

It isa LOCALvariable. It has been passed as an argument. Similarly there are a few arrays also that are passed along with this temparature variable. These pointers again are pointing to 'undefined address'( It is the actual debugger comment.)

All these local variables have been defined in the multiple thread session.

The arrays that I have been passing, some of them I have declared as 'Private' at the start of openMP loop.

Regards,

Hrushi

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,347 Views

Hrushi,

subroutine SingleThreaded
real :: LocalVariable
LocalVariable=0.0
c$omp parallel do private(LocalVariable)
do i=1,count
call MultiThreaded(LocalVariable)
end do
c$omp end parallel do
end subroutine SingleThreaded

In the above program LocalVariable uninitialized within the parallel section

The above is equivilent to

subroutine SingleThreaded
real :: LocalVariable
LocalVariable=0.0
c$omp parallel
call HiddenSubroutine
c$omp end parallel
end subroutine SingleThreaded

subroutine HiddenSubroutine
real :: LocalVariable
integer :: i
do i=1,count
call MultiThreaded(LocalVariable)
end do
end subroutine HiddenSubroutine

If you wish to pass in initializations then use the OMP COPYIN construction

Post the statement declaring the arrays.

Note, If the array is allocatable and allocated outside the parallel region then when entering the parallel section with private instantiation of the array the allocatable arraywill not allocated.

Also, considering adding the AUTOMATIC attributeto the array declaration(s) to force stack copy of the array descriptor(s). Depending on compiler options (and without AUTOMATIC) you might end up with a static copy of the array descriptor (as you would with the SAVE attribute).

Stepping through with the debugger in the Disassembly Window will show that a variable reference is static or stack based.

LOCAL variable to C/C++ programmer means variable declared in scope ({}) without keyword static.

LOCAL variable in Fortran means visible only in scope (this may be static or stack based).

Jim

0 Kudos
hrushi_397
Beginner
1,347 Views

Hi Jim,

Well I tried the COPYIN clause as you suggested but it desnot seem to work out.

My code goes something like this:

INTEGER I,J,L

INTEGER,DIMENSION(1000)::GRID

DO I=1, COUNTER

>L=SOME EXPRESSION

!$OMP PARALLEL DO NUM_THREADS(1) PRIVATE(VARIABLE_LIST) COPYIN(L,GRID)

DO J=1, GRID(L)

>CALL mySUBROUTINE(VARIABLE_LIST)

END DO

Now the problem that I am facing while I debug the program is that the value of L. It has got to be somewhere within 1 to 10. However when I debug the program value at first breakpoint shown by > symbol in above code is perfectly fine. However when the control comes to second breakpoint in the program, value of L goes out of bound. At the same time, addresses of some of the array pointers point to 'undefined address'.

While you talked about allocatable arrays, they have been converted into fixed size arrays & those fixed size arrays have been made private in variable list, that was to avoid data-race & at the same time to make program run. These array values have been initialized just before openMP loop starts, & they have been equated back to their size just after openMP loop ends.

Hrushi

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,347 Views

The problem may be with the Debugger determining the scope of the variables. Try:

INTEGER I,J,L
INTEGER,DIMENSION(1000)::GRID
call Init_GRID(GRID)
DO I=1, COUNTER
>L=SOME EXPRESSION
!$OMP PARALLEL DO NUM_THREADS(1) SHARED(L, GRID) PRIVATE(VARIABLE_LIST)
DO J=1, GRID(L)
>CALL mySUBROUTINE(VARIABLE_LIST)
END DO
!$OMP END PARALLEL DO

The compiler may have created a transparentsubroutine call to the !$OMP region and the debugger symbol table may be (and in older versions of the compiler deffinately were) goofed up to the point where you could not examine stack local variables within a parallel region. This was or is being fixed.

Also note...

Just in case you are not a Fortran programmer...
In Fortran "DO J=1, GRID(L)" is examined once at loop initialization.
i.e. an iteration count is produced at the DO statement
the ENDDO decriments the iteration count and branches to
the statement following the DO if additional iterations required.
If your mySUBROUTINE modifies L or modifies GRID(L)
this will not alter the iteration count of the DO J loop.
You cannot terminate the loop by setting GRID(L) = 0
or by setting J=HUGE(J)

Jim

					
				
			
			
				
			
			
			
			
			
			
			
		
0 Kudos
hrushi_397
Beginner
1,347 Views

Hi Jim,

I have already tried to work out the approach you have mentioned. Its not working.

One more thing...its not the mySUBROUTINEthat modifies the value of L & grid( L). It is the !$omp declaration itself that modifies the value of L & grid(L). As soon as control enters the parallel region, modification of value takes place. I know that it should not, however I can't help it. I desperately tried to undo it, but thats going in vain. Why should in parallel region a variable should change its value? I guess that in declaration of parallel region, pointers are getting modified, though I am not sure of it.

Hrushi

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,347 Views

Hrushi,

Try the following experiment

INTEGER I,J,L
INTEGER,DIMENSION(1000)::GRID
call Init_GRID(GRID)
DO I=1, COUNTER
>L=SOME EXPRESSION
write(*,*) loc(L),L,loc(GRID(1)),GRID(1)
!$OMP PARALLEL DO NUM_THREADS(1) SHARED(L, GRID) PRIVATE(VARIABLE_LIST)
DO J=1, GRID(L)
write(*,*) loc(L),L,loc(GRID(1)),GRID(1)
>CALL mySUBROUTINE(VARIABLE_LIST)
write(*,*) loc(L),L,loc(GRID(1)),GRID(1)
END DO
!$OMP END PARALLEL DO

With L and GRID shared the location of L and GRID will remain unchanged.

Note, Outside the parallel region L will appear as a stack local variable without a reference pointer to L (on the stack as a dummy argument). Inside the parallel region L will likely use a reference pointer. the LOC(L) should resolve to the same address. However, if you look in a dissassembly window the code will look different. Outside the parallel region L is (should be) referenced directly on the stack. Inside the parallel region the stack location containing the address of L will be moved to a register and then the register will be referenced indirectly to access L.

If L is private, then the local copies will be different.

Also, note the second write(*,*) following the call to mySUBROUTINE.

If L andGRID(1) get wacked after the call then there is something wrong in how you are passing the arguments (value verses reference, address of array descriptor verses address of GRID(1), calling protocal as to who cleans up the stack, etc...).

Jim Dempsey

0 Kudos
Reply