next up previous contents
Next: Hiding Templates from Volume Up: Implementation Previous: Dynamic Plugins   Contents

Speed Optimization - Avoiding Late Binding

Throughout the design process of OpenVL, there is one factor that was given the most importance - speed. The design of OpenVL is influenced by the famous 80-20 rule: 80 percent of the execution time is spent in 20 percent of the code. OpenVL thus concentrates on making that 20 percent of the code as fast as possible, while making the other 80 percent as flexible as possible. Since the part of OpenVL which will execute most often is volume data access, making that part as fast as possible is our primary goal.

Figure 8: Different ways to access data in OpenVL.
\includegraphics[width=270pt]{images/data_access.eps}

In the earlier sections we saw that the data layouts are implemented as dynamic plugins which are loaded at run time. This gives us the flexibility to run the user applications on different data layouts - even new data layouts about which the user application has no prior knowledge. Since this needs run time function redirection, we use the late binding (virtual functions) mechanism provided by C++. This gives a very fast implementation of data access while maintaining the flexibility we desire.

In certain cases however, virtual function calls might not be fast enough. It is well known that virtual function calls are slightly slower than direct function calls due to pointer dereferencing. Direct function calls however are generated by the compiler at compile-time only. To provide data access using direct calls, the prior knowledge of the data layout would be needed. We have designed the data access mechanism such that the prior knowledge of data layout will give the user application the maximum speed via direct function calls, thus avoiding virtual calls. In Figure 8 we show the options the user has to access data. If the speed of virtual function calls is enough, the user can use the VirtualCall iterator to access the volume data. This iterator automatically calls the correct iterator functions at run time using a virtual function call. In case direct function calls are desired, the user can call the appropriate iterator directly as shown by the solid arrows.

There is also a third option which can combine the two previous options. The user can use a macro defined in OpenVL to call the appropriate iterator directly, or in case the iterator is unavailable, the macro will call the VirtualCall iterator. This type of data access will be fast for data layouts which provide iterator implementations at run time and slow for other layouts which do not. However, this has the drawback of adding some code bloat to the user application because every routine will be implemented for each supported layout type and data type. We suggest that this method be used only where there is a significant performance hit when compared to using the VirtualCall iterator.


next up previous contents
Next: Hiding Templates from Volume Up: Implementation Previous: Dynamic Plugins   Contents
Sarang Lakare 2002-12-23