[f2py] F2PY: Unable to prevent Fortran ordered array copy

Ravi Kanda <[email protected]>
Newsgroups gmane.comp.python.f2py.user
Message-ID <[email protected]>
Hi,

I have been using Numpy+f2py for a couple of years, and the combination 
  has worked well for me for many types of problems.  However, I have 
never been able to prevent F2PY from copying arrays even though I 
initialize them as Fortran ordered in the calling python script.  I have 
spent a considerable time looking in the archives (both F2PY & NUMPY) 
and found several leads to diagnosing array-copy problems (see results 
below), but none of them seem to work for me.

-----------------------
System/Compiler Info:
-----------------------
I am currently running on a Dell workstation with the following setup:
[Fedora Core 3 Linux (32-bit)]/
[Python:2.5.1]/[Numpy:1.0.4]/[f2py:2.45.241_1926]/
[F90-compiler:Intel 10.0].

Actually, I have tried wrapping using three different compilers: 
INTEL-F90 (IFORT, v.10.0), PGF90 (v.8.0), and GFORTRAN (gcc 4.2.0).  But 
array-copying persists in every case.

For reference, I have uploaded a TGZ file containing 7 text files to the 
following location (the filelist - test sources, PYF, and output - are 
summarized below this email): 
ftp://ftp.gps.caltech.edu/pub/rkanda/MemoryDeallocTest.tgz.  If 
attachments are a preferred way to send files, please do let me know.

The problem details and test results are as follows ...

----------------------
Problem description:
----------------------
I've to call a wrapped f90 function several times from the same python 
script, each time with different array dimensions (please see 'mm.f90', 
and 'call_mm.py' in TGZ file).  I want to be able to handle arrays of 
size 10000x10000 (1e8 elements).  I am finding that after each call, 
memory allocated during f2py array-copy (which I haven't been able to 
eliminate) is not being deallocated, and I find (using 
numpy.testing.utils.memusage()) that the additional memory usage after 
each call is about the same as the size of all the F2PY-copied-arrays 
for that call (see 'call_mm.py').  So, the virtual memory usage 
mushrooms, and when it gets to ~2GB (I have 1.5 GB of RAM, and 6 GB of 
virtual memory on my system), I encounter a "Core Dump".  [As an aside, 
I am not sure whether the core-dump is due to a "per-process-limit" for 
Python or the 32-bit Linux OS].  I am using the "-DF2PY_REPORT_ATEXIT" 
and "-DF2PY_REPORT_ON_ARRAY_COPY=1" options on the f2py command line to 
document the array copying (see wrapPYF.csh & SampleOutput*.txt files in 
TGZ file).

--------------------------
Summary of observations:
--------------------------
1) I have tried wrapping using three different compilers: INTEL-F90 
(IFORT, v.10.0), PGF90 (v.8.0), and GFORTRAN (gcc 4.2.0).  But 
array-copying persists in every case.

--------------------------
2) The wrapper generated using 'intent(in,out,overwrite)' "works", but 
creates a copy every time (see 'mm_new.pyf' & 
SampleOutput*_InOutOverwrite.txt in TGZ file).  I also tried by 
explicitly setting the 'overwrite_<VAR>' flags to 1, just to be sure. 
If I test with a constant array size (i.e., disable array size update 
during each iteration), then I see that arrays are being overwritten for 
every iteration AFTER the first.  So, 'intent(in,out,overwrite)' seems 
to do the job except for the first array copy.
	On the other hand, intent(inout), or intent(inplace) do not work, and I 
get the following run-time error: "pymm.error: failed in converting 4th 
argument `a' of pymm.mmfunc.mm to C/Fortran array" (see 
SampleOutput*_InPlace.txt for details).

--------------------------
3) I have tried defining the numpy array in fortran ordering several 
ways (order keyword in array or asarray, asfortranarray; see 
'call_mm.py'), but all of them result in arrays being copied before 
being passed to the wrapped function (pymm.mmfunc.mm).

--------------------------
4) I tested that my numpy installation was working correctly:
 >>>
 >>> a = reshape(arange(15),(3,5))
 >>> a
array([[ 0,  1,  2,  3,  4],
         [ 5,  6,  7,  8,  9],
         [10, 11, 12, 13, 14]])
 >>> b = reshape(arange(15),(3,5),order='f')
 >>> b
array([[ 0,  3,  6,  9, 12],
         [ 1,  4,  7, 10, 13],
         [ 2,  5,  8, 11, 14]])
 >>> isfortran(a)
False
 >>> a.flags['F_CONTIGUOUS']
False
 >>> isfortran(b)
True
 >>> b.flags['F_CONTIGUOUS']
True
 >>>

--------------------------
5) I use a similar test procedure to (4) in the attached python script, 
'call_mm.py'.  But right after these checks, when I run 
"pymm.has_column_major_storage(a)" (pymm is the wrapped module, and 'a' 
the array), however, the result is '0' (ZERO - i.e, not an f-contiguous 
array)!  I don't understand why f2py is not recognizing a 
fortran-ordered array assigned within numpy.  I am guessing 
'intent(inplace)' or 'intent(inout)' in (1) are not working for me 
because of this same reason - f2py does not seem to recognize the input 
array as being fortran-ordered.  Also see (6) below.

--------------------------
6) I also tried converting all input arrays before calling the wrapped 
function (pymm) using "a = pymm.as_column_major_storage(a)", but that 
gives me an error.  To illustrate, for the array defined in (4) above, 
this function fails as follows:
 >>>
 >>> a
array([[ 0,  1,  2,  3,  4],
         [ 5,  6,  7,  8,  9],
         [10, 11, 12, 13, 14]])
 >>> pymm.has_column_major_storage(a)
0
 >>> a = pymm.as_column_major_storage(a)
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
pymm.error: expected array object
 >>>

--------------------------
Given that there are several previous posts where one of the above seems 
to have worked for others, it seems like there is something I don't 
understand about f2py array passing, or f2py directives in the signature 
file.  Perhaps there is a subtle problem with my f2py installation.

I am including all my test-scripts & output files (along with the f2py 
command used to wrap the f90 code & wrapping log) at the location below. 
  I will really appreciate any help/suggestions in this regard.

Thank you very much in advance for your time.
Ravi.

================================================================
Test file summary (the following files can be downloaded from:
ftp://ftp.gps.caltech.edu/pub/rkanda/MemoryDeallocTest.tgz)
----------------------------------------------------------------
1. mm.f90     : Fortran test function
2. mm_new.pyf : Edited signature file for 'mm.f90'
3. wrapPYF.csh: C-Shell script to wrap 'mm.f90', using 'mm_new.pyf'
4. mm_f2pywrap.log: F2PY compile screen output
5. call_mm.py : Python script calling the wrapped 'mm.f90'
6. Sample*_InOutOverwrite.txt: Screen output from 'call_mm.py' for 
'intent(in,out,overwrite)' case.
7. Sample*_InPlace.txt: Screen output from 'call_mm.py' for 
'intent(inplace)' case.
=================================================================
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.