← Back to team overview

ffc team mailing list archive

Adding code generation backends to FFC and generating C code

 

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

FFC generates C++ code, which makes sense given that the UFC interface
is specified in C++. It is however a limitation when you want to use
FFC to generate code for another interface/backend, as we do with
PyOP2 (see our branch https://code.launchpad.net/~mapdes/ffc/pyop2).

We require all kernels (and by kernels I mean basically every UFC
function that is generated e.g. tabulate_tensor) to be C99 for a
number of reasons - which are not relevant for this discussion but
I'll mention some of them for those who are curious:

1) We target multiple hardware architectures (CUDA and OpenCL among
others), which have limited support for C++. We want to keep the door
open for more architectures in the future and the lowest common
denominator will likely remain to be C.

2) We rely on pycparser to be able to parse kernels for
instrumentations s.a. adding memory space attributes for OpenCL. To
the best of our knowledge there's no reliable and easy to use C++
parser available in Python.

It turns out that FFC generated code is in fact C99, apart from:

a) Usage of functions like sqrt, abs, pow from the std namespace.

b) Usage of C++ exceptions (only when hitting invalid orientation
markers).

c) Usage of the static keyword (which has a different meaning in C99).

So far we have overcome this issue by specializing those code snippets
we were using and which had C99 incompatible code in them. It seems
this is not a very elegant nor maintainable solution.

At the moment FFC isn't quite set up for adding another code
generation backend that generates C99 code without introducing lots of
special cases. So my questions are:

1) Is there value in restructuring FFC to better accommodate adding
code generation backends which do not target UFC? If so, where do we
start? You're welcome to look at how we're doing it at the moment,
which is an attempt to minimize changes to existing code and the FFC
pipeline and clearly not very elegant.

2) Is there an easier way of generating C kernels given the
constraints a-c we've identified above?

These questions are related but I think could be treated separately. I
can think of a few options for 2):

i) Add using declarations to the UFC kernel templates in ufc_utils and
drop the std:: prefix in the function bodies. This would (mostly)
allow functions bodies to remain C99 compatible.

ii) Add Python string templates to the code snippets allowing to
choose between C++ and C99 specific statements where necessary and
depending on the code generation target i.e. replace "std::sqrt" by
"%(sqrt)s" and then replace that template depending

I think ii) is more flexible but more "messy" but i) alone might be
too limiting and a combination of both might be required.

In our branch we have taken great care to make sure we pass all tests
and don't break any UFC/DOLFIN functionality and we plan to add
additional tests exercising the pyop2 code generation backend. We'd
like to propose our branch for merging into the FFC trunk in the near
future and are therefore very keen on any ideas how to overcome the
issues I outlined and any comments and suggestions on the changes we
propose.

Florian
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iEYEARECAAYFAlErjFgACgkQ8Z6llsctAxYZIACg5N+c9uxeWwEoJ1x8SSy2rKHo
z/8AoMwa9cAwQwWeGEUi86g/Eilf/ms9
=E3VL
-----END PGP SIGNATURE-----

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature


Follow ups