Unsupported local variable

Hi,
I’m no programmer, i didn’t work with fortran until now, as for C i have just a very basic idea. OpenACC i have no clue also.
But still i wanted to play a bit with openacc. I had a fractal example in C (or c++ i have no clue which one) that outputs a fractal in text. The program is multicore CPU. and it works.
I wanted to change it for openacc but it seems that complex type is not supported by pgi in c. Seems that fortran has no issues with it.
Anyway
After trying and trying and trying and trying i changed the code a bit
so the code looks like this

program test
	integer,parameter :: width=100 ,height=100
    integer :: maxiter
    complex :: center,span,begin
    character(len=99) :: char_a,char_b,char_c
    integer :: x,y,n,a,b
    complex :: c
    character (len=1) :: ch
    character (len = *), parameter::charset = ".,c8M@jawrpogOQEPGJ";
    real :: temp
	integer::testare,line
	complex::temp3
	integer::temp4
	character(len=1),dimension(height,width)::lines
	character(len=height*width)::string
	center=(-0.7, 0) 
    span=(2.7, -1*(4/3.0)*2.7*height/width)
    begin = center-span/2.0
    maxiter = 100000
	ch=" "
	
	!$acc parallel loop 
	do line=0,height-1
		
		do x=0,width-1
			c = begin + CMPLX(x * span%re / (width +1), line * span%im / (height+1))
			n=0
			temp3=c
			temp4=0
			testare=0
			do n=0,maxiter-1
				if (abs(temp3)>=2) then
					testare=1
				else 
					temp3=temp3*temp3+c
				end if
				if (testare==0) temp4=temp4+1
			end do
			n=temp4
			if (n == maxiter) n = 0
			ch = " "
			if(n > 0) then
			lines(line+1,x+1)=charset(mod(n,len(charset))+1:mod(n,len(charset))+1)
			else
!			lines(line+1,x+1)=ch  <---give error
			lines(line+1,x+1)=" "
			end if
		end do
		
	end do
	!$acc end loop
	do line=1,height
		do x=1,width
			write(*,'(a,$)') lines(line,x) !<---give error
		end do
		print*,"|"
	end do

end program test

the problem is that if i try to compile it as it is now i get Unsupported local variable error
If i comment the write line from last loop i can compile the code. and it seems it works. i have no clue if it does since i can’t see the result.
Compiling it without -acc the code works without problems.
It seems that lines(a,b) does not accept values from another variable and i can’t read values from it after the loop is done.

What am i doing wrong?
Is there any openacc guide for noobies?

The first thing you should do is make sure the code compiles
and runs correctly without -acc.

As you add !$acc directives that same code should still work when
compiled without -acc.

The second thing you should do is move any I/O (reads or writes)
that take place in OpenACC sections to before or after the section.
Why ask the GPU to ask the CPU to do I/O?

Third, do one section of code at a time. For example, choose a loop
that should run faster on a GPU, and add the OpenACC directives.
Then compile without -acc , to make sure it still works. Then compile
with -acc and see if it works. Then go to the next OpenACC opportunity, and add directives, and so on.

OpenACC.org would be a good resource for learning about OpenACC.

If you start with a program that works, and incrementally enable
a section of code at a time with OpenACC directives, you can determine very quickly where and what the issues are. This is a
real advantage when programming GPUs.

As far as teaching fortran, there is lots of help online.
I would suggest the simpler the Fortran code you use, the faster it
can become on the GPU, if there is enough computational work to do.
Computation is what GPUs do.

dave

The code works without -acc. It compiles and run as it should
The loop for i/o is outside acc
But still that i/o code outside acc, gives error when compile with -acc
Thats what i don’t understand.


edit: is this error related to http://www.pgroup.com/userforum/viewtopic.php?p=21045&sid=4ffcd16633c09b7cf14dccaa521a0a8c ?

Hello,

I have forwarded the problem to Engineering, to determine if this is
a new bug, or a problem we found handling characters in OpenACC.

If you want to get some success, look for examples that perform
computation on REALs or COMPLEX numbers, and avoid character
handling.

dave

i just tried to make lines array from char to integer
Now i can assign lines(x,y)=variable inside the !$acc code.
The variable has the return of ICHAR(character).
This give no error anymore.

But i still can’t compile the program if output on last loop is on.
This time the error is different:

test:
24, Accelerator kernel generated
Generating Tesla code
25, !$acc loop gang, vector(100) ! blockidx%x threadidx%x
26, !$acc loop seq
32, !$acc loop seq
24, Generating implicit copyout(lines(:,:))
26, Complex loop carried dependence of prevents parallelization
32, Loop carried scalar dependence for testare at line 38
Loop carried scalar dependence for temp3 at line 33,36
FMA (fused multiply-add) instruction(s) generated
nvvmCompileProgram error: 9.
Error: E:\Temp\pgacc2dfWAp78z0XMb.gpu (259, 47): parse use of undefined value ‘@_staticinit_test
pgnvd-Fatal-Could not spawn C:\PROGRA~1\PGICE\win64\17.10\bin\pgnvvm.exe
PGF90-F-0155-Compiler failed to translate accelerator region (see -Minfo messages): Device compiler exited with error status code (test2.f95: 1)
PGF90/x86-64 Windows 17.10-0: compilation aborted

Does the compiler tries to accelerate last loop also even though its outside the !$acc directives?
I’ve tried to change

write(*,'(a,$)') lines(line,x)

with

t(line,x)= lines(line,x)

just to see if the output is the problem. It seems that i still get the same error.

Please include your modified program and how you compiled it.

We would like to repeat it.

Windows 10?

dave

The code

program test
	integer,parameter :: width=100 ,height=100
    integer :: maxiter
    complex :: center,span,begin
    integer :: x,y,n,a,b
    complex :: c
    !character (len=1) :: ch
	integer::ch
    character (len = *), parameter::charset = ".,c8M@jawrpogOQEPGJ";
    real :: temp
	integer::testare,line
	complex::temp3
	integer::temp4
	integer,dimension(height,width)::lines,t
	character(len=height*width)::string
	center=(-0.7, 0) 
    span=(2.7, -1*(4/3.0)*2.7*height/width)
    begin = center-span/2.0
    maxiter = 100000
	ch=ichar(" ")
	!$acc parallel loop
	do line=0,height-1
		do x=0,width-1
			c = begin + CMPLX(x * span%re / (width +1), line * span%im / (height+1))
			n=0
			temp3=c
			temp4=0
			testare=0
			do n=0,maxiter-1
				if (abs(temp3)>=2) then
					testare=1
				else 
					temp3=temp3*temp3+c
				end if
				if (testare==0) temp4=temp4+1
			end do
			n=temp4
			if (n == maxiter) n = 0
			ch = ichar(" ")
			if(n > 0) ch=ichar(charset(mod(n,len(charset))+1:mod(n,len(charset))+1))
			!else
!			lines(line+1,x+1)=ch  <---give error
			!lines(line+1,x+1)=ichar(" ")
			!end if
			lines(line+1,x+1)=ch !<--seems to work if lines in array of integer
		end do
	
	end do
	!$acc end loop
	do line=1,height
		do x=1,width
			write(*,'(a,$)') char(lines(line,x)) !<---give error
		end do
		print*,"|"
	end do
	!print*,lines(10,50) !<- give error
end program test

was compiled with -acc -Minfo, on windows 8.1 and linux

The example you chose still performs char() operations, which we
agree is currently a problem.

I see no point in pursuing this further.

Time to find a new example.

Sorry to bother you again.
I change it to integer only (i hope)
Now it works for small matrix (500x500)
If i want it 1000x1000 or 500x1000 program crash together with display driver.

code is

program test
	integer,parameter :: width=500 ,height=500
    integer :: maxiter
    complex :: center,span,begin
    integer :: x,y,n,a,b
    complex :: c
	integer::ch
	integer,dimension(19)::charset=(/0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9/)
    real :: temp
	integer::testare,line
	complex::temp3
	integer::temp4
	integer,dimension(height,width)::lines,t
	center=(-0.7, 0) 
    span=(2.7, -1*(4/3.0)*2.7*height/width)
    begin = center-span/2.0
    maxiter = 100000
	!$acc parallel loop
	do line=0,height-1
		do x=0,width-1
			c = begin + CMPLX(x * span%re / (width +1), line * span%im / (height+1))
			n=0
			temp3=c
			temp4=0
			testare=0
			do n=0,maxiter-1
				if (abs(temp3)>=2) then
					testare=1
				else 
					temp3=temp3*temp3+c
				end if
				if (testare==0) temp4=temp4+1
			end do
			n=temp4
			if (n == maxiter) n = 0
			ch = 0
			if(n > 0) ch=charset(mod(n,size(charset))+1)
			lines(line+1,x+1)=ch
		end do
	
	end do
	!$acc end loop
	do line=1,height
		do x=1,width
			write(*,"(i1,$)") lines(line,x)
		end do
		print*,"|"
	end do
	call acc_set_device(acc_device_nvidia)!<--recommended after program crashed
end program test

and the “error” that occurs together with display driver crash when the array is 600x600 (or larger)

PGI: “acc_shutdown” not detected, performance results might be incomplete.
Please add the call “acc_shutdown(acc_device_nvidia)” to the end of your application to ensure that the performance results are complete.

Accelerator Kernel Timing data
C:\Users\Vasile\test3.f95
test NVIDIA devicenum=0
time(us): 30
18: data region reached 1 time
18: data copyin transfers: 1
device time(us): total=30 max=30 min=30 avg=30
18: compute region reached 1 time
18: kernel launched 1 time
grid: [600] block: [128]
device time(us): total=0 max=0 min=0 avg=0

the program was compiled with

pgfortran -acc -Minfo test3.f95 -o test3.exe -Mlarge_arrays

Well at least it works. even if its just for a small size area