Re: Avoid slow initialization of DynamicModule
- To: mathgroup at smc.vnet.net
- Subject: [mg84466] Re: [mg84436] Avoid slow initialization of DynamicModule
- From: John Fultz <jfultz at wolfram.com>
- Date: Wed, 26 Dec 2007 05:09:38 -0500 (EST)
- Reply-to: jfultz at wolfram.com
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
* 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...
By default, this actually executes as...
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...
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...
which will typeset into
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
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
Sorry for the very long explanation, but I wanted to be as clear as possible.
Hope you found it helpful.
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,
Prev by Date:
Re: Re: Re: how fill PolarPlot?
Next by Date:
Re: Can this problem be solved in Mathematica
Previous by thread:
Re: Avoid slow initialization of DynamicModule
Next by thread:
Re: Re: Avoid slow initialization of DynamicModule