← Back to team overview

ufl team mailing list archive

Re: JIT compilation

 

I've implemented this in UFL such that:

    a = ...*dx
    ...
    fd = a.form_data()

ensures that a FormData object is
computed once and only once.
So jit can do this:

def jit(form):
    formdata = form.form_data()
    ...

Martin



On Tue, Feb 24, 2009 at 10:51 PM, Martin Sandve Alnæs
<martinal@xxxxxxxxx> wrote:
> On Tue, Feb 24, 2009 at 10:12 PM, Anders Logg <logg@xxxxxxxxx> wrote:
>> The FFC JIT compiler (and any other JIT compiler that DOLFIN uses)
>> must be able to return FormData as well as the compiled form. DOLFIN
>> uses this to extract coefficients and elements.
>
> Agreed.
>
>> Without caching, the JIT compiler gets the form, generates form data,
>> generates the C++ code which is sent to Instant. Instant then returns
>> the compiled form and the JIT compiler returns the form + form data to
>> DOLFIN.
>
> So far so good.
>
>> With caching, the JIT compiler gets the form, sends it to Instant (or
>> rather a wrapper that returns an appropriate hash and signature). Then
>> Instant returns the compiled form. This means that the form data is
>> missing.
>
> Which is the way it has to be for Instant to be an independent project.
>
>> FFC solves this by attaching the form data to the form:
>>
>>  form.form_data = form_data
>>
>> This way, the form data is available both when the in-memory cache is
>> used and when the disk cache is used. In the first case, the form has
>> been JIT compiled before so the object has form_data attached to
>> it. In the second case, the signature needs to be computed which means
>> that also the form data will be computed.
>>
>> Would it be possible/desirable to attach form data to a UFL form? Or
>> will it be necessary to keep a separate form data cache in the JIT
>
> Let me just think loudly.
>
> The thing is, the Form that the user passes in to jit won't be
> the same Form as Formdata contains. Derivatives must be
> expanded to know the right number of form arguments,
> and indices and arguments are renumbered to get a canonical
> repr independent of the order which forms are defined in the
> application.
>
> Unless this behaviour is changed, attaching form data to
> the form will mean that "a.form_data.form != a", but
> a.form_data.form still represents the same form, and
> FormData does nothing compiler- or representation-specific.
>
> What does this mean? Take this pseudocode:
>
> # make some form:
> a = ...*dx
>
> # compile some times with jit and then with different options to make
> it interesting:
> form1, formdata1 = jit(a)
> form2, formdata2 = jit(a)
> form3, formdata3 = jit(a, options = non_default_options)
> form2, formdata2 = jit(a)
>
> # instant ensures this:
> form1.__module__ == form2.__module__
> form1.__module__ == form4.__module__
>
> # and the different options should lead to this:
> form3.__module__ != form2.__module__
>
> # you want this:
> a.form_data == formdata1 # computed and attached to a in first jit call
> a.form_data == formdata2 # reused in second jit call
> a.form_data == formdata3 # if not, we'll get major problems
> a.form_data == formdata4
>
>
> I was sceptical at first, but I think this will work out.
> As long as "fd = FormData(a)" is a completely deterministic
> operation with no options that can change the result,
> attaching it to a poses no problems. In particular, FormData
> must be independent of any dolfin or form compiler options.
>
>> compiler. It sort of makes the in-memory cache of Instant pointless
>> (for form compilation) since the JIT compiler might then as well cache
>> the compiled form (as it did before this was added to Instant).
>
> Not true. In PyDOLFIN, forms with different coefficients will
> have different formdata (which dolfin may or may not keep
> a cache of as we discuss now), but still be the same
> compiled form, which instant caches separately.
>
> Martin
>


Follow ups

References