Overview¶
Fython is Fortran with a Python syntax. If performance requirements periodically forces you out of Python, with Fython you won’t feel it
hello.fy
real offset = 0
def fast_sum:
real in v(1e9)
real res r
r = 0
for i in [1, 1e9]:
r += v[i] + offset
print 'The sum is {:sum(v)}'
The loop above is automatically parallelized by the Fortran compiler that powers Fython.
Usage in Python is as simple as
hello.py
import fython
import numpy as np
hello = fython.load('.hello')
offset = hello.offset()
v = fython.Real(shape=[1e9])
offset = 10
v[:] = np.random.uniform(0, 1, 1e9)
hello.fast_sum(v)
Features¶
Performance¶
The Fython language is a syntaxtic binding for the Fortran language. Any instruction you write in Fython is translated to Fortran, with the exact same meaning. The translated Fortran code is then compiled to machine instructions. There is no boiler plate code generation or LLVM in between. What you code is what you run (WYCIWYR).
Python Syntax¶
Fython allows to write Fortran code
with Python syntax.
No messy end xyz
everywhere.
No more %
for object attributes,
enjoy the car.color
notation.
No more concatenation puzzle,
use multiline string """xyz"""
.
No more &
for multiline instruction,
simply use parenthesis
many(
arguments,
and,
more,
)
Write class with class, enjoying attribute getter and setter.
class Nucleon(Atom):
real position = 1
int weight = 10
def pget fission:
self inout
self.weight /= 2
Nucleon n
n.fission
print 'weight {:n.weight}'
Python Comfort¶
Fython import system is modeled after Python. You can define Fython modules accross several folders. They will all correctly compile and link.
import .variance = var
import stat.mean(*)
import .svm(vapnik, least_square_svm=lsq_svm)
Fython has a stack trace for fast error spotting. Say goodbye to those uninformative runtime errors.
fython sigsegv: segmentation fault
module stat.buggy
function subboom
line 7
stack trace (lineno function module) (most recent first)
7 subboom stat.buggy
3 boom stat.buggy
Fython print
and read
function are intuitive.
The format mini-language is that of Fortran plus several improvements.
Interpolating variables can be specified directly in the string like Perl.
print './out' 'x is {:x}'
print .file 'column 2 is {v:x[:,2]}
read .data: x y z
Pycessor¶
Use Python to easily do your preprocessing magic
import numpy
real pi = |numpy.pi|
# lazy initialization of exotic random variate
real v(1e3)
|
for i in range(1000):
write('v[i] = {:f}'.format(numpy.random.uniform()))
|
Any expression enclosed in bars is evaluated against the imported Python module. The return value of a pycession can be any valid Fython code.
Template¶
Overload of a function or a class can be created with template interpolation
def temp f:
T in x
T res r
r = x + 10
def g = f(T=real)
When this is not sufficient, a whole package can be templatized
quicksort.fy
import type_provider(target_class=T)
def quicksort(x):
T x(:)
int i
int res r
r = 0
for i in [1, size(x)]:
r += x[i].less_than(x[i+1])
consumer.fy
import quicksort(*)
||type_provider = maxwell, target_class = Atom ||
int r
Atom a(10)
r = quicksort(a)
FyTypes
You can send Python object by reference to Fython using the intuitive fytypes
from fython import *
m = load('stat.mean')
nb_element = Int(value=3)
x = Real(value=[1, 2, 3])
result = Real()
m.mean(nb_element, x, result)
print(result[:])
When using a fytype, you always access or modify its value with a slice. Wheter the value is a scalar or an array.
x[:2] += 10
result[:] *= 10
Changes made by Fython are propagated back to Python
m.moving_average_in_place(x)
print('moving average is:', x[:])
You can also access and modify global Fython variables
n = m.roundoff_tolerance()
n[:] = 1e-5
All the above works for real, integer and string variables of any dimension
cities = Char(size=30, value=['montreal', 'tokyo', 'santiago'])
result = Char(size=30)
m.word_mean(nb_element, cities, result)
Wrap Fortran code and shared library
All intrinsic Fortran module are avalaible in Fython. Other Fortran modules are avalaible once they are in your Python path
import iso_c_binding(*)
import fftw.discrete_cosine_transform(*)
real x(10)
fftw_dct(x)
Putting a Fortran module in the Python path is usually done with
import sys
sys.path.append('~/fftw')
A Shared library can be imported once you have a Fortran or a Fython interface for it
import mkl.include.mkl_vsl(*)
import mkl.lib.intel64.libmkl_intel_lp64(*)
The first import is the fortran interface mkl_vsl.f90
.
The second import is for the shared object library libmkl_intel_lp64.so
.
The requirement for these imports to work is that the mkl root directory must be in your Python path. This is usually achieve with
import sys
sys.path.append('/opt/intel')
Installation¶
git clone https://github.com/nicolasessisbreton/fython
cd fython
python3 setup.py install
Dependencies:
Platform:
Linux