← Back to team overview

ffc team mailing list archive

Re: Adding code generation backends to FFC and generating C code

 

On 26 February 2013 15:26, Florian Rathgeber
<florian.rathgeber@xxxxxxxxx> wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> On 26/02/13 09:33, Martin Sandve Aln₩s wrote:
>> Just want to chip in here. FYI I'm currently adding a new
>> representation to ffc based on lp:uflacs, where I reuse some of the
>> quadrature representation code and new generate tabulate_tensor
>> bodies with completely separate code. I'm using my own code
>> formatting utilities, which probably has its pros and cons. I've
>> also done some minor refactoring in ffc, so there will be a merge
>> soonish (when Anders gets the dolfin-ufc-geometry branch up to
>> speed). Hopefully this won't be difficult for you to merge with
>> your branch, I don't think it's too extensive.
>
> Thanks for the heads up, it sounds like once your branch gets merged
> things will be a bit easier for us. Is it the
> ffc-uflacs-ufc-geometry-merged branch?
>
>> As for the language differences, I think it will be practical to
>> generate code kernels that are both C99 and C++ compatible:
>>
>> a) Usage of functions like sqrt, abs, pow from the std namespace.
>>
>> - Instead of using std::foo in the code, we can add "using
>> std::foo;" in code targeted for C++. Makes the generated code
>> cleaner as well.
>
> Where do you think the right place for this would be? FFC or ufc_utils?
>
>> b) Usage of C++ exceptions (only when hitting invalid orientation
>> markers).
>>
>> - This can be removed and checked on the dolfin side like
>> everything else, as I see it it's mainly there for a safe gradual
>> introduction of the orientation markers.
>
> We're not hitting this kernel in our code at the moment, so we could
> just ignore it for now.
>
>> c) Usage of the static keyword (which has a different meaning in
>> C99).
>>
>> - Are you sure?
>> http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1012 I
>> think we can wrap global static declarations in an unnamed
>> namespace if the code is target for C++, and otherwise use the same
>> declarations.
>
> I think I was wrong about that, static seems to be a perfectly legal
> keyword also in C99 the way it's used in FFC generated code. It's a
> bug in pycparser failing to parse that statement, I'll look into
> fixing it.
>
>> These should all be simple changes. Adding fortran support however
>> will not be as simple, because the code formatting framework is
>> quite low level and close to the structure of C/C++ code, so that's
>> a completely different project. Probably easier to generate C and
>> call from fortran then :)
>
> We don't have any plans to support Fortran at the moment, but I can
> see how it would be an issue as the FFC code generation is modeled
> quite closely around C/C++.
>
>> Martin
>>
>>
>> On 26 February 2013 08:00, Kristian ￘lgaard
>> <k.b.oelgaard@xxxxxxxxx <mailto:k.b.oelgaard@xxxxxxxxx>> wrote:
>>
>> On 25 February 2013 17:07, Florian Rathgeber
>> <florian.rathgeber@xxxxxxxxx <mailto:florian.rathgeber@xxxxxxxxx>>
>> wrote: 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:
>>
>>> The idea is that code formatting for C++ is handled by the
>>> module cpp.py which implements the format dictionary. To generate
>>> code for a different target language, you should implement a new
>>> format dictionary in c.py (or fortran.py).
>
> I understanding where this design is coming from. However, the point I
> was trying to make is that C++ and C99 are sufficiently close to be
> handled by the same code generator.

But wouldn't it just be a matter of importing the format from cpp.py to your
c.py and then call update on the relevant entries?
(I'm only talking pure FFC here, not ufc_utils)
Then it will work with the solution you devise below for the imports.

>
>>> Then in modules like codegeneration.py where we currently do:
>>
>>> from ffc.cpp import format, indent
>>
>>> the import shold be depending on the target language. At least,
>>> that's how the design was intended. However, as C++ has been the
>>> only target language available in FFC since the beginning, the
>>> concept has never been tested and there are probably many cases,
>>> like the above, which are C++ spefic.
>
> Conditional imports in module scope are a massive pita when depending
> on runtime values as would be the case here. You'd probably want to
> either add another level to the existing dictionaries and index by
> language and item, or wrap the format dictionary in a class which you
> instantiate with a backend and then do the conditional import to
> populate it.

Sure, I just meant to point to where the issues might be.
Either of you proposed methods sound good to me.

Kristian

>>> The above approach would be the _correct_ way as I see it, but
>>> might require a bit of work initially. However, I think it will
>>> worthwhile in the end, particularly if you want to merge your
>>> code back into FFC.
>
> I hope I can convince you we shouldn't be crossing that bridge just yet.
>
> Florian
>
>>> Kristian
>>
>> 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
>>>
>>>
>>> _______________________________________________ Mailing list:
>>> https://launchpad.net/~ffc Post to     : ffc@xxxxxxxxxxxxxxxxxxx
>>> <mailto:ffc@xxxxxxxxxxxxxxxxxxx> Unsubscribe :
>>> https://launchpad.net/~ffc More help   :
>>> https://help.launchpad.net/ListHelp
>>>
>>
>> _______________________________________________ Mailing list:
>> https://launchpad.net/~ffc Post to     : ffc@xxxxxxxxxxxxxxxxxxx
>> <mailto:ffc@xxxxxxxxxxxxxxxxxxx> Unsubscribe :
>> https://launchpad.net/~ffc More help   :
>> https://help.launchpad.net/ListHelp
>>
>>
>>
>>
>> _______________________________________________ Mailing list:
>> https://launchpad.net/~ffc Post to     : ffc@xxxxxxxxxxxxxxxxxxx
>> Unsubscribe : https://launchpad.net/~ffc More help   :
>> https://help.launchpad.net/ListHelp
>>
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.11 (GNU/Linux)
> Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/
>
> iEYEARECAAYFAlEsxhsACgkQ8Z6llsctAxZTTACfelbvWxRY8SF3QQp9EPEuEQoG
> Dq4AoMGb9Gju7JTrl7eYL+FQ6AH3TybB
> =MolL
> -----END PGP SIGNATURE-----
>


References