Jonas Juselius [email protected]
HPC@UiT
layout: false
- There exists no perfect language for all tasks
- Languages have different stenghts:
- Python is excellent for driving computations and pre- and post-processing results
- Fortran is suitable for high-performance linear algebra and mathematical programming
- C++ supports advanced data structures, generic programming and more
- C is the mother tongue of UNIX
- Haskell is purely functional and lazy
- Coupling functionality from existing programs
- C is the common denominator
- Export needed functionality to C
- Often necessary to modularize the host code:
- init()
- step()
- finalize()
- + accessors
- Couple either directly or via Cython
- Use CMake to build and link
- Use iso_c_binding
- Calling conventions:
- Pass by value
- bind(C)
- c_ptr, c_loc, c_f_pointer
- Column vs. row major matrices
module ccall
use, intrinsic :: iso_c_binding
implicit none
interface
function cwork(n, matrix) result(r) bind(c)
import
integer(C_INT), value :: n
type(C_PTR), value :: matrix
real(C_DOUBLE) :: r
end function
end interface
contains
function work(n, matrix) result(r)
integer :: n
real(8), dimension(n,n), target :: matrix
real(8) :: r
r = cwork(n, c_loc(matrix(1,1)))
end function
end module
module fwork_module
use, intrinsic :: iso_c_binding
implicit none
contains
function fwork(n, vec) result(r) bind(c)
integer(C_INT), value :: n
type(C_PTR), value :: vec
real(C_FLOAT) :: r
real, dimension(:), pointer :: fvec
call c_f_pointer(vec, fvec, [n])
call do_some_work(fvec, r)
end function
end module
int fwork(int, float *); // normally defined in header file
int work() {
int x;
float y[100];
x = fwork(100, y);
return 0;
}
C++ cannot be directly linked due to name mangling.
#ifdef __cplusplus
class Workhorse {
public:
Workhorse() {}
virtual ~Workhorse() {}
int work(int n, float *vec) { return n; }
}
#else
typedef struct Workhorse Workhorse;
#endif
#ifdef __cplusplus
extern "C" {
#endif
int workhorse__work(AClass *a, int n, float *vec) {
return a->work(n, vec);
}
#ifdef __cplusplus
}
#endif
-
Compile Python to C!
- Speedup Pyhton
- Call external C/C++ functions directly
- Pass arrays via numpy
- Use CMake!
-
https://github.com/bakerjonas/python-tutorials/tree/master/Cython
def f(double x):
return x**2-x
def integrate_f(double a, double b, int N):
cdef int i
cdef double s, dx
s = 0
dx = (b-a)/N
for i in range(N):
s += f(a+i*dx)
return s * dx
cimport numpy as cnp
import numpy as np
cdef extern from "fwork.h":
int fwork(int, float *)
def py_fwork(int n):
cdef cnp.ndarray ax, c
ax = np.arange(a, b, (b-a)/float(n))
c = np.ndarray(n), dtype=np.float32, order='F')
i = fwork(n, <float *> ax.data)
return (i, c)
import cyspeed
import pywork
print py_fwork(1000)
print integrate_f(0.0, 100.0, 500)
project(CyPy)
enable_language(Fortran)
find_package(Python REQUIRED)
include(UseCython)
add_library(fwork SHARED
fwork.f90
fwork.h
)
cython_add_module(pywork
pywork.pyx
)
target_link_libraries(pywork
fwork
)
- FFI (Foreign Functions Interface):
- Call C functions from Haskell
- Export Haskell functions to C