Skip navigation
NASA Logo, National Aeronautics and Space Administration
Modeling Guru Banner
Currently Being Moderated

F2Py and Static Libraries

VERSION 1 
Created on: Apr 29, 2013 11:21 PM by Jules Kouatchou - Last Modified:  Apr 30, 2013 12:11 AM by Jules Kouatchou

We want to show an example how to use F2Py to link a Fortran subroutine with pre-built static libraries.

Assume that we have three methods to compute a matrice multiplication and we want to write Fortran subroutines to implement those methods (each method is contained in its own file.

 

Method 1: Loop

 

      subroutine matMult_loop1(A, B, C, n1, n2, n3)

      INTEGER n1, n2, n3
      DOUBLE PRECISION A(n1,n2)
      DOUBLE PRECISION B(n2,n3)
      DOUBLE PRECISION C(n1,n3)

      INTEGER i, j, k

      do j = 1, n3
         do i = 1, n1
            C(i, j) = 0.
            do k = 1, n2
               C(i, j) = C(i, j) + A(i, k)*B(k, j)
            enddo
         enddo
      enddo

      RETURN

      end subroutine matMult_loop1

 

Method 2: Loop

 

      subroutine matMult_loop2(A, B, C, n1, n2, n3)

      INTEGER n1, n2, n3
      DOUBLE PRECISION A(n1,n2)
      DOUBLE PRECISION B(n2,n3)
      DOUBLE PRECISION C(n1,n3)

      INTEGER i, j, k

      do j = 1, n3
         do i = 1, n1
            C(i, j) = 0
         enddo
         do k = 1, n2
            do i = 1, n1
               C(i, j) = C(i, j) + A(i, k)*B(k, j)
            enddo
         enddo
      enddo

      RETURN

      end subroutine matMult_loop2

 

 

Method 3: Intrinsic Fortran function (matmult)

 

      subroutine matMult_func(A, B, C, n1, n2, n3)

      INTEGER n1, n2, n3
      DOUBLE PRECISION A(n1,n2)
      DOUBLE PRECISION B(n2,n3)
      DOUBLE PRECISION C(n1,n3)

      C = matmul(A,B)

      RETURN

      end subroutine matMult_func

 

 

Creation of the Static Library

 

 

You can use the following Makefile to create (assuming that the name of the source files are  matMult_loop1.F90, matMult_loop2.F90 and matMult_func.F90) the static library:

 

FC = gfortran

FFLAGS = -fPIC

SRCS_F = $(wildcard  matMult_*.F90)
OBJS   = $(SRCS_F:.F90=.o)

all: $(OBJS)
        ar crs libmatMultiplication.a $(OBJS)

clean:
        rm -f *.o *.mod *.so *.a


.SUFFIXES:
.SUFFIXES: .o .f .F90 .h

.F90.o: $(FSOURCE)
        $(FC) -c $(FFLAGS) $?

 

After you create the Makefile file, you can issue the command:

 

 

make

 

and you will get the static library: libmatMultiplication.a

 

 

Fortran Subroutine Relying on the Static Library

 

Now, let us write a Fortran subroutine (contains in a file named matrixMult.F90) that will use the library:

 

 

      subroutine matrixMult(A, B, C, n1, n2, n3, iCase)

      INTEGER, intent(in) :: n1, n2, n3
      INTEGER, intent(in) :: iCase
      DOUBLE PRECISION, intent(in) :: A(n1,n2)
      DOUBLE PRECISION, intent(in) :: B(n2,n3)
      DOUBLE PRECISION, intent(out) :: C(n1,n3)

      SELECT CASE (iCase)
         CASE (1)
            CALL matMult_loop1(A, B, C, n1, n2, n3)
         CASE (2)
            CALL matMult_loop2(A, B, C, n1, n2, n3)
         CASE (3)
            CALL matMult_func (A, B, C, n1, n2, n3)
      END SELECT

      RETURN

      end subroutine matrixMult

 

 

Generating the Python Module with F2Py

 

Here are the command lines to generate the module (to be used in a Python script) by F2Py:

 

 

f2py -m multMatrices -h sgnFile.pyf matrixMult.F90
f2py -c --fcompiler=gnu95 sgnFile.pyf matrixMult.F90 -L{Full_Path_to_Library} -lmatMultiplication

 

You will obtain the file multMatrices.so.

 

Writing a Python Code to Test Matrix Multiplications

 

 

The following Python code (named f2py_matrixMult.py) can be used to test the the different matrix multiplication methods:

 

 

#!/usr/bin/env python


import numpy as np
from time import *
import sys
import multMatrices

n1 = int(sys.argv[1])
n2 = int(sys.argv[2])
n3 = int(sys.argv[3])

A = np.random.rand(n1,n2)
B = np.random.rand(n2,n3)

#-------
# Case 1
#-------
beg = time()
AB = multMatrices.matrixmult(A,B,1)
end = time()

print 'Loop1: time for','AB'+str(np.shape(AB)),'=','A'+str(np.shape(A)),'B'+str(
np.shape(B)),'is', end - beg,'s'

#-------
# Case 2
#-------
beg = time()
AB = multMatrices.matrixmult(A,B,2)
end = time()

print 'Loop2: time for','AB'+str(np.shape(AB)),'=','A'+str(np.shape(A)),'B'+str(np.shape(B)),'is', end - beg,'s'

#-------
# Case 3
#-------
beg = time()
AB = multMatrices.matrixmult(A,B,3)
end = time()

print 'matmul function: time for','AB'+str(np.shape(AB)),'=','A'+str(np.shape(A)),'B'+str(np.shape(B)),'is', end - beg,'s'

 

To run the Python script, issue the command:

 

./f2py_matrixMult.py n1 n2 n3

 

where n1, n2 and n3 are the dimensions of the matrices:

 

Timing Numbers

 

n1,n2,n3
Method 1
Method 2
Method 3
1000,1500,100015.259.611.33
1500,1500,150040.0921.613.32
1500,2000,150055.6228.824.49
Comments (0)
USAGov logo NASA Logo - nasa.gov