MathGroup Archive 2007

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Avoid slow initialization of DynamicModule

  • To: mathgroup at smc.vnet.net
  • Subject: [mg84467] Re: [mg84436] Avoid slow initialization of DynamicModule
  • From: "Thomas Muench" <thomas.muench at gmail.com>
  • Date: Wed, 26 Dec 2007 05:10:10 -0500 (EST)
  • References: <200712240946.EAA06236@smc.vnet.net>

Dear John,

Thank you for your detailed reply, you suggestion worked like charm.
It is quite unexpected behavior at first, but when thinking about it,
it makes sense.

I changed your code a little bit to restore the encapsulation, because
I really did not like the idea that you have to load your image data
into a given variable named "img", and that the program would fail any
other way. It is quite simple:

stratification[image_]:=
Module[{img=image},
DynamicModule[.... same code as before....]
]

You can now call the function with
stratification[whatever]

and it will work. The only disadvantage is that the data will now be
in memory twice, namely as "img" (in the Module) and as "whatever" (as
global variable). For really *very* large image data that consumes to
much memory on my laptop for the kernel to survive. But other than
that it is fine.

Thank you again very much

thomas

On Dec 25, 2007 6:47 AM, John Fultz <jfultz at wolfram.com> wrote:
> I'm happy to see users such as yourself creating such impressive interfaces with
> Mathematica.  What you've done here is very nice, and does a great job of
> exploiting the new version 6 features.
>
> As to the source of your problems, you can forget any inherent overhead in
> Dynamic.  The system scales extremely well, and the overhead it introduces is
> trivial.  The principle sources of the typical Dynamic troubles have to do with
> what the Dynamic is evaluating.  The problems I often see are...
>
> * Dynamic has dependencies on too many variables which are triggering too often.
> So the Dynamic recomputes much more often than necessary.  This is the problem
> which can lead to 100% CPU usage despite the fact that the Dynamic doesn't
> appear to change (i.e. it keeps recalculating the same result over and over
> again).
>
> * Dynamic is given more to compute than necessary, making every triggered
> Dynamic too expensive to compute.
>
> * The computation Dynamic is given just requires too much time, and keep the
> front end and/or kernel in limbo while it's computing.
>
> You've set up your interface pretty well, and have avoided these problems.  But
> due to the scale of your data, another factor is coming into play which is rare
> in most other Dynamic examples.
>
> When Mathematica sends a very large result from the kernel to the front end,
> things can start to really slow down and consume a lot of memory.  Each of the
> following contributes to that slowdown, both due to computational overhead and
> memory consumption (which contributes to memory page faults)...
>
> * The kernel code which creates the typeset form of the expression
> * The transmission of the result over MathLink
> * The creation and representation of the result in the front end
>
> Your example unwittingly exposes the worst possible behaviors for all three of
> the above cases.  When you do...
>
> img=<large thing>
> stratification[img]
>
> By default, this actually executes as...
>
> stratification[<large thing>]
>
> which is no problem for the kernel.  But because of the way that function
> variable replacement works, this eventually becomes, e.g....
>
> Dynamic[ListLinePlot[<large thing>]] (*I'm simplifying your code slightly here*)
>
> which then typesets into...
>
> DynamicBox[MakeBoxes[ListLinePlot[<large thing>], StandardForm]]
>
> which is then sent, in its entirety to the FE.  The process of creating the
> DynamicBox[] is very expensive because of <large thing>, and then <large thing>
> is sent to the FE to be represented inside the Dynamic.  Then the FE sends
> <large thing> back to the kernel in the evaluation of ListLinePlot, and the
> kernel finally sends the much more moderately-sized resulting graphic back.  It
> is as if you took <large thing> and copied and pasted it directly in the
> definition of 'stratification'.  Of course, this is even worse because <large
> thing> shows up in three separate Dynamics (the ListLinePlot, the main Raster,
> and the list of slice Rasters).
>
> To illustrate the point, as well as show a very simple workaround, here's a very
> simple change to make.  Change...
>
> stratification[img_]:=
>
> to
>
> stratification[image_]:=
>
> but do *not* change any of the references in the body of stratification.  Assign
> your source data to 'img' as you did in this email and re-evaluate everything in
> a fresh kernel.  Now, instead of 'img' being replaced as a function variable, it
> will be used a global variable.  Now, the evaluation will be...
>
> Dynamic[ListLinePlot[img]]
>
> which will typeset into
>
> DynamicBox[MakeBoxes[ListLinePlot[img], StandardForm]]
>
> and what will be sent to the FE will be no more than the 3 bytes of the variable
> name 'img' (plus another several bytes to qualify that it's in the Global`
> context).  Then, the FE will evaluate
>
> ListLinePlot[img]
>
> and the value of img will never have been sent to the FE...only the graphic
> resulting from ListLinePlot[img].  And, in your example, this will actually be
> much smaller because you never create a graphical representation of all of img,
> but only pieces of it.  I tried this with a random set of data of the size you
> describe, and it was extremely efficient...taking only a few seconds (on a very
> fast and new machine...your mileage may vary).
>
> Now, normally I would say this isn't the best practice.  It's generally good for
> interfaces to well-encapsulated.  They should use variables which reside in
> DynamicModules[] and not have side effects by using or creating global variables
> (unless using global variables is part of the purpose of the interface, of
> course).  But there's no way to fully encapsulate this interface without the
> undesirable effects you're seeing.
>
> You could store a variable in a private context which represents the source data
> for the image.  That would encapsulate it somewhat.  But, for as long as you're
> going to have upwards of 500 megabytes of source data, you're going to have to
> make sure it doesn't get duplicated, typeset, or transmitted to the FE to be
> efficient.
>
> Sorry for the very long explanation, but I wanted to be as clear as possible.
> Hope you found it helpful.
>
> Sincerely,
>
> John Fultz
> jfultz at wolfram.com
> User Interface Group
> Wolfram Research, Inc.
>
>
>
>
> On Mon, 24 Dec 2007 04:46:19 -0500 (EST), Thomas Muench wrote:
> > Dear MathGroup,
> >
> > I have written an application (Mathematica 6.0.1 on Windows XP, code
> > see below) with which I want to analyze image data (3D stacks acquired
> > with a confocal microscope). The program works very nicely in
> > principle (with small sample data), but it does NOT work when the data
> > is of the size that I usually deal with. The dynamic display does not
> > even initialize. The computer works hard for about 40 minutes, and
> > then Mathematica quits without an error message.
> > My image stacks usually have dimension e.g. 63x4x512x512 (each image
> > has x-y-dimension 512x512, 4 color channels at each z-level, and on
> > the order of 60 levels).
> >
> > My dynamic display consists of 3 graphics (2 of which are
> > LocatorPanes, and 1 a simple ListLinePlot), which don't take too much
> > time to be created when I evaluate the corresponding graphic commands
> > outside of anything "Dynamic" (it takes 1 sec, 0.2 sec and .01 sec,
> > respectively). So the problem should not be the creation of the
> > graphics from the image stacks. I think it has something to do with
> > the overhead that is connected with dynamic displays, whatever that
> > may be. In fact, once the Dynamic interface is created in the
> > notebook, all the manipulations I do with it are quite swift.
> >
> > Here is some timing information that I obtained: To initialize the
> > display with sample data of size 63x4x50x50, it takes about 8 seconds.
> > 4 times as large (63x4x100x100) takes about 30 seconds, i.e. about 4
> > times as long. If it would keep scaling linearly like that, I would
> > expect about 15 minutes for my full data, but, as mentioned, it
> > crashes after 40 minutes. I guess apart from the crash, linearity
> > brakes down because of memory issues.
> >
> > My question is: Why is there such a large overhead? Is there a way to
> > avoid it? In my particular case, I do not need "usability" of the
> > dynamic interface preserved over sessions. I need to quickly load and
> > display the data, do some manipulations to extract some numbers, and
> > then move on to the next data set. So even if it worked in 15 minutes
> > it would not be very useful.
> >
> > Since the problem scales with data size, I tried to use
> > LocalizeVariables->False, but this does not seem to be a valid option
> > for DynamicModule. Any other suggestions to get rid of (at least part
> > of) the overhead?
> >
> > Thank you very much,
> > thomas
>
>
>


  • Prev by Date: Re: Re: Re: how fill PolarPlot?
  • Next by Date: Re: ReplaceAll problem
  • Previous by thread: Avoid slow initialization of DynamicModule
  • Next by thread: Re: Avoid slow initialization of DynamicModule