Debugging and performance optimization tips
Debugging and performance optimization tips
The general workflow when defining your network with Gluon API is either:
-
build sequentially using
nn.Sequential
ornn.HybridSequential
-
inherit from
nn.Block
ornn.HybridBlock
Debugging
When debugging your MXNet code, remember the following:
Do NOT hybridize for debugging
The difference between imperative style (Gluon non-hybridized) and symbolic style (Gluon hybridized) is:
- imperative style is define-by-run
- symbolic style is define-then-run
Basically, that means the execution path changes when calling hybridize
on your network inherited from HybridBlock
or HybridSequential
(note that inheriting directly from Block
is the same as not hybridizing your network). For efficiency, symbolic code does not keep the intermediate results and so it would be hard to debug and examine the intermediate outputs. Therefore, if you want to examine the intermediate results for debugging, do NOT hybridize. Once everything is working as expected, then you can hybridize
and enjoy the speed up.
Please checkout the d2l for more details about the hybrid-programming model.
Use naive engine
It is also useful to set the environment variable MXNET_ENGINE_TYPE='NaiveEngine'
prior to running your (end-to-end) code. This setting disables multi-threading and the execution engine will be synchronous, so you can examine the backtrace more easily. Remember to change it back to either the default 'ThreadedEnginePerDevice'
or 'ThreadedEngine'
.
For more details, here is a comprehensive tutorial on interactive debugging on YouTube.
Performance optimization
Following up on using the environment variable MXNET_ENGINE_TYPE
for debugging, here are the available environment variables that affect the performance of your code.
Please refer to this presentation for more information on debugging and performance optimization.