On Monday April 25 2011 15:16:06 Garth N. Wells wrote: > On 25/04/11 23:04, Johan Hake wrote: > > On Monday April 25 2011 14:53:22 Johan Hake wrote: > >> On Monday April 25 2011 14:44:23 Garth N. Wells wrote: > >>> On 25/04/11 22:29, Johan Hake wrote: > >>>> I am working on a simple solution, where we store everything in the > >>>> original ufl form. > >>>> > >>>> I might have something soon. > >>> > >>> OK. > >>> > >>> I played around with something like this, but had some issues when the > >>> form changes (i.e. a += . . . ) after being preprocessed. > >> > >> Oups! I guess my "fix" wont get this either... Maybe we need to destroy > >> the form_data object whenever += ... are called? > > > > I do not think this will be a problem, as += here returns a new object. I > > am actually not sure how this works, but I think because __iadd__ is > > _not_ > > > > implemented in Form, Python probably turns: > > L += L > > > > into > > > > L = L + L > > > > which will result in a new form and now problems. > > Have you tested it?
Yes. > Your approach is more elegant than my hack, so it > will probably work. I assigned the preprocessed form to the original, i.e. > > a_tmp = preprocess(a) > a_tmp += a > > which broke, I think because of the index renumbering performed by > preprocess. Yes, we shall not expose the preprocessed form to the user. Johan > Garth > > > Johan > > > >> Johan > >> > >>> Garth > >>> > >>>> Johan > >>>> > >>>> On Monday April 25 2011 14:26:18 Garth N. Wells wrote: > >>>>> On 25/04/11 22:08, Anders Logg wrote: > >>>>>> On Mon, Apr 25, 2011 at 07:40:21PM -0000, Garth Wells wrote: > >>>>>>> On 25/04/11 20:00, Johan Hake wrote: > >>>>>>>> On Monday April 25 2011 11:26:36 Garth Wells wrote: > >>>>>>>>> On 25/04/11 18:51, Anders Logg wrote: > >>>>>>>>>> On Mon, Apr 25, 2011 at 05:11:41PM -0000, Garth Wells wrote: > >>>>>>>>>>> On 25/04/11 17:53, Johan Hake wrote: > >>>>>>>>>>>> On Monday April 25 2011 08:59:18 Garth Wells wrote: > >>>>>>>>>>>>> On 25/04/11 16:47, Johan Hake wrote: > >>>>>>>>>>>>>> Commenting out the cache is really not a fix. The problem is > >>>>>>>>>>>>>> within dolfin. Isn't there another way to deal with this? > >>>>>>>>>>>>> > >>>>>>>>>>>>> It is a fix if the cache isn't needed. > >>>>>>>>>>>> > >>>>>>>>>>>> Sure. > >>>>>>>>>>>> > >>>>>>>>>>>>>> First: How much penalty are there with a disabled memory > >>>>>>>>>>>>>> cache. Maybe the problem isn't that bad? > >>>>>>>>>>>>> > >>>>>>>>>>>>> I don't get the point of this cache. The way it is now, a > >>>>>>>>>>>>> form is only preprocessed if it hasn't already been > >>>>>>>>>>>>> preprocessed, which seems ok to me. The old code tried to > >>>>>>>>>>>>> avoid some preprocessing, but it was highly dubious and I > >>>>>>>>>>>>> doubt that it was effective. > >>>>>>>>>>>> > >>>>>>>>>>>> I think the preprocessing stage actually do take some time. > >>>>>>>>>>>> AFAIK the preproces stage essentially do two things. It > >>>>>>>>>>>> creates a canonical version of the Form so two Forms that are > >>>>>>>>>>>> the same, but constructed at different times are beeing > >>>>>>>>>>>> treated equal wrt form generation. Then are DOLFIN specific > >>>>>>>>>>>> guys extracted. I am not sure what takes the most time. We > >>>>>>>>>>>> should probably profiel it... But if it is the latter we could > >>>>>>>>>>>> consider putting another cache in place which is more robust > >>>>>>>>>>>> wrt changing DOLFIN objects. > >>>>>>>>>>> > >>>>>>>>>>> It should be easy to avoid the overhead of preprocessing by > >>>>>>>>>>> keeping the object in scope. If the object changes, the only > >>>>>>>>>>> robust way to make sure that the form is the same as one in the > >>>>>>>>>>> cache is to compare all the data. This requires preprocessing > >>>>>>>>>>> the form, which then defeats the purpose of a cache. It may be > >>>>>>>>>>> possible to add a lightweight preprocess to UFL, but I don't > >>>>>>>>>>> think that it's worth the effort or extra complication. > >>>>>>>> > >>>>>>>> I think a light weight version might be the way to go. This is > >>>>>>>> then stored in memory cache. If we are able to strip such a form > >>>>>>>> for all DOLFIN specific things we would also prevent huge memory > >>>>>>>> leaks with mesh beeing kept. > >>>>>>>> > >>>>>>>> Then we always grab DOLFIN specific data from the passed form > >>>>>>>> instead of grabbing from the cache. Not sure how easy this will be > >>>>>>>> to implement, but I think we need to explore it, as the DOLFIN > >>>>>>>> specific part of the form really has nothing to do with the > >>>>>>>> generated Form. > >>>>>>>> > >>>>>>>> Martin: > >>>>>>>> Why is it important to have the _count in the repr of the form? I > >>>>>>>> guess that is used in ufl algorithms? Would it be possible to > >>>>>>>> include a second repr function, which did not include the count? > >>>>>>>> This would then be used when the signature is checked for. We > >>>>>>>> could then use that repr to generate a form which is stored in > >>>>>>>> the memory cache. This would then be tripped for any DOLFIN > >>>>>>>> specific objects. This should work as the _count attribute has > >>>>>>>> nothing to do with what code gets generated, but it is essential > >>>>>>>> for internal UFL algorithms, right? > >>>>>>>> > >>>>>>>>>> I'm not very happy with this change. > >>>>>>>>> > >>>>>>>>> The bright side is that slow and correct is a better starting > >>>>>>>>> point than fast but wrong ;). > >>>>>>>>> > >>>>>>>>> An easy fix is to attach the preprocessed form to a Form object. > >>>>>>>>> This would work robustly if we can make forms immutable once > >>>>>>>>> they've been compiled. Is it possible to make a Python object > >>>>>>>>> immutable? > >>>>>>>> > >>>>>>>> We can probably overload all setattribtue methods which prohibits > >>>>>>>> a user to write to these but it might not be possible to prohibit > >>>>>>>> a user to change attributes on instances owned by the Form. I > >>>>>>>> guess this is similare to the difficulties of preserving > >>>>>>>> constness in C++, but I think it is even harder in Python. > >>>>>>> > >>>>>>> What if we have the FFC jit compiler return the preprocessed form, > >>>>>>> and inside dolfin.Form simply do > >>>>>>> > >>>>>>> class Form(cpp.Form): > >>>>>>> def __init__(self, form, . . .. ) > >>>>>>> .... > >>>>>>> > >>>>>>> (...., preprocessed_form) = jit(form, . . . . ) > >>>>>>> > >>>>>>> form = preprocessed_form > >>>>>>> > >>>>>>> ..... > >>>>>>> > >>>>>>> This way, form will have form_data, and the FFC jit function will > >>>>>>> know not to call ufl.preprocess. > >>>>>> > >>>>>> Here's another strange thing. In the JITObject class, we have two > >>>>>> functions: __hash__ and signature. As far as I understand, the first > >>>>>> is used to located objects (generated code/modules) in the Instant > >>>>>> in-memory cache, while the second is used for the on-disk cache. > >>>>>> > >>>>>> >From some simple tests I did now, it looks like the __hash__ > >>>>>> > > >>>>>>> function > >>>>>> > >>>>>> does not need to any significant speedup. The JIT benchmark runs > >>>>>> just as fast if I call signature from within __hash__. > >>>>>> > >>>>>> Furthermore, the __hash__ function must also be broken since it > >>>>>> relies on calling id on the form. > >>>>>> > >>>>>> Ideally, we should get Instant to handle the caching, both in-memory > >>>>>> and on-disk, by providing two functions __hash__ (fast, for > >>>>>> in-memory cache) and signature (slow, for on-disk cache). > >>>>>> > >>>>>> Since __hash__ cannot call id, it must be able to attach a unique > >>>>>> string to the form (perhaps based on an internal counter in FFC). > >>>>>> My suggestion would be to add this to UFL, something like set_hash > >>>>>> and hash (which would return None if set_hash has not been called). > >>>>>> If Martin does not like that, we should be able to handle it on the > >>>>>> DOLFIN side. > >>>>>> > >>>>>> So in conclusion: no in-memory cache in FFC (handled by Instant) and > >>>>>> FFC attaches a hash to incoming forms so that Instant may recognize > >>>>>> them later. > >>>>> > >>>>> The code that I disabled was caching preprocessed forms, so I don't > >>>>> see how this can be handled by Instant. > >>>>> > >>>>> Garth > >>>>> > >>>>>> Maybe even better: Instant checks whether an incoming object has a > >>>>>> set_hash function and if so calls it so it can recognize objects it > >>>>>> sees a second time. > >>>>>> > >>>>>> I'm moving this discussion to the mailing list(s). > >>>>>> > >>>>>> -- > >>>>>> Anders > >>>>>> > >>>>>> _______________________________________________ > >>>>>> Mailing list: https://launchpad.net/~ffc > >>>>>> Post to : ffc@lists.launchpad.net > >>>>>> Unsubscribe : https://launchpad.net/~ffc > >>>>>> More help : https://help.launchpad.net/ListHelp > >>>>> > >>>>> _______________________________________________ > >>>>> Mailing list: https://launchpad.net/~ufl > >>>>> Post to : u...@lists.launchpad.net > >>>>> Unsubscribe : https://launchpad.net/~ufl > >>>>> More help : https://help.launchpad.net/ListHelp > >> > >> _______________________________________________ > >> Mailing list: https://launchpad.net/~ufl > >> Post to : u...@lists.launchpad.net > >> Unsubscribe : https://launchpad.net/~ufl > >> More help : https://help.launchpad.net/ListHelp _______________________________________________ Mailing list: https://launchpad.net/~ffc Post to : ffc@lists.launchpad.net Unsubscribe : https://launchpad.net/~ffc More help : https://help.launchpad.net/ListHelp