FAQ - Miscellaneous tips for improved performance and timing


Q: How can i improve the drawing performance and timing of my PTB-3 code?
A: There are many measures that one can combine in order to increase reliabilty of presentation timing and drawing performance. Many of them are not neccessary on modern hardware unless you create very demanding and complex stimuli. However, they may be useful for old hardware and it is always a good idea to write your code in a portable and efficient way.

System setup:

Matlab:

Dual display operation:

Running two displays simultaneously requires more VRAM memory and computational ressources in your gfx-card, plus some additional management overhead in the graphics driver. This can cause lower graphics performance and therefore lead to missed stimulus onset deadlines when running complex stimuli on high resolution, high refresh rate displays, especially when using older mobile graphics chips with a low amount of local VRAM. To minimize these effects, try the following:

Programming:

Psychtoolbox output to the Matlab window

The amount of verbosity of PTB can be controlled via the Screen('Preference', 'Verbosity', level); command. Use low settings for level to minimize output to the Matlab window: Reduced clutter and saved time for printing. Use high (or default) settings during development of your code and during first test runs to make sure that you get informed by PTB of possible issues with your setup or code!

Settings for the level parameter and their meaning:
  1. No output at all.
  2. Only severe error messages.
  3. Errors and warnings.
  4. Additional information, e.g., startup output when opening an onscreen window.
  5. Even more information and hints.
  6. Very verbose output, mostly useful for debugging PTB itself. Usually not what you want.

Preloading of functions:

Matlab M-Files and especially MEX files do have some additional delay on first invokation (Matlab needs to find and load them, compile or link them, they need to perform some internal initialization). This can be significant, e.g., multiple hundred milliseconds. For time critical studies, use each function once before your trial loop to "preload" the function before first use.

M-Functions are faster than M-Scripts:

Add the function keyword to the top of your experiment script after initial testing and debugging. Matlab precompiles functions into some optimized code at load time, so they execute faster than scripts (M-Files without function keyword).

If the executed m-file is a script then Matlab reparses and interprets each statement again every time the script is executed and no optimizations are applied. It is as if you type commands into the matlab window, just typing very fast.

Functions, however, are precompiled and optimized by Matlab's JIT compiler at load time, and during execution, so they are faster. One problem of dynamic optimization at runtime ("hot spot optimization") is that loops in your code may execute slower during the first few iterations than in the remaining iterations, because they are optimized during runtime. Because of this, it is recommended to dry-run your code for a few trials before starting your actual experiment. This is beautiful for most applications, but can create headaches for benchmarking and deterministic timing. The other problem is the lack of documentation and control about these features. The strategies apparently change with each new matlab release, as new optimization features are added under the hood.

This JIT mechanism is what gives Matlab a speed advantage over Octave for poorly written code, whereas there's basically no difference for well written code in most cases. For maximum performance and most deterministic timing it is best to optimize your code yourself as described in Mathworks documentation, so the JIT has to do less guesswork and runtime optimization and you'll get better performance/timing from the start. And of course use ptb's timing functions wisely to immunize your code against such behaviours as much as possible.

Other M-code optimizations: Good coding practices

With some googling, quite a bit can be found on good coding practices. I have pasted a few links that seem good below.
It is suggested you start by reading MCFEX: Writing Fast MATLAB Code.
See Peter Acklam's MATLAB array manipulation tips and tricks for many techniques for writing vectorized code.
The below links seem to have some useful information and tips too (add any links that you found useful and do not simply duplicate information already introduced in other links):
Speed MATLAB by optimizing memory access
For tips on measuring performance of scripts, see MCFEX: MATLAB Performance Measurement. This file also contains a section A Catalog of Noise, which introduces you to warming up cold code and to sources of potential timing variability.

But don't forget, If your code works well and timing is good, don't spend hours optimizing it--the payoff for your work would be almost nil and you might even introduce unforseen bugs. In my view, this statement doesn't hold if your new to MATLAB and coding practices that work well. Experiment and learn! do take your time to optimize, following the pointers from the links above. That way you wil make good practice your own and you will learn to think in good code (vectorized code is easier on your working memory also).

Realtime scheduling:

For time critical code, use the Priority(prio) command to raise Matlab to realtime-priority mode. Select the prio value via prio=MaxPriority(...) to get the highest suitable priority for your needs in a portable, operating system independent way. Don't forget to disable realtime mode via Priority(0) at the end of your script!

Optimal Code structure:

If you experience missed frame presentation deadlines, try to structure your code inside your animation/trial loop as follows:
  1. All Screen drawing commands, e.g., Screen('DrawDots',...) , Screen('DrawText', ...), Screen('DrawTexture', ...).
  2. The command Screen('DrawingFinished', win[, clearmode]); where clearmode is the same optional flag that you'll optionally pass to the Screen('Flip', win); command. This will tell PTB that stimulus drawing for this frame is finished, so it can perform a couple of optimizations, e.g., perform potential stimulus post-processing operations immediately and in parallel to the execution of your non-graphics Matlab code.
  3. All commands not related to graphics, e.g., sound output, keyboard/mouse/response box queries, Matlab code, ...
  4. The vbl=Screen('Flip', win [,when]); command to trigger stimulus onset. Providing a when timestamp is recommended. It allows PTB to further optimize drawing when it knows, when exactly the stimulus should be shown. It also allows for higher reliability of the built-in frame skip detector and it allows for very robust stimulus onset timing. On most hardware and operating systems, the returned vbl timestamp is a highly accurate and robust timestamp of the time your stimulus was flipped onto the display, unaffected by all the timing noise that is invariably present in most operating systems.

While use of Screen('Flip', ...) with the vbl and when arguments is nearly always recommended for studies where you care about frame accurate timing, use of the Screen('DrawingFinished',...) command is optional and not needed for many studies. Its worth a try if you have very complex and demanding stimuli, tight deadlines at high framerates or old and slow hardware: It doesn't hurt to use it, but it doesn't help in all cases either.

DriftWaitDemo.m in the PsychDemos folder of PTB is a good example of how to provide timed onset of stimuli.

Reduced VRAM usage on graphics hardware with very small VRAM

Try if adding a Screen('Preference', 'ConserveVRAM', x); with x=1 or 2 or 3 or 4 to the top of your script makes things better or worse. Reduced VRAM pressure, but higher load for system RAM and bus. Under these settings, PTB doesn't cache textures in VRAM anymore but only keeps them in system memory.

Speeding up specific PTB drawing commands

Tests:

The following scripts may be useful to assess display timing on your setup:

...to be continued, stay tuned...
Valid XHTML :: Valid CSS: :: Powered by WikkaWiki