VLFeat supports for threaded computations can be used to take advantage of multi-core architectures. Threading support includes:

# Using VLFeat from multiple threads

VLFeat can be used from multiple threads simultaneously if proper rules are followed.

• A VLFeat object instance is accessed only from one thread at any given time. Functions operating on objects (member functions) are conditionally thread safe: the same function may be called simultaneously from multiple threads provided that it operates on different, independent objects. However, modifying the same object from multiple threads (using the same or different member functions) is possible only from one thread at any given time, and should therefore be synchronized. Certain VLFeat objects may contain features specific to simplify multi-threaded operations (e.g. VlKDForest).
• Thread-safe global functions are used. These include thread-specific operations such as retrieving the last error by vl_get_last_error and obtaining the thread-specific random number generator instance by vl_get_rand. In these cases, the functions operate on thread-specific data that VLFeat creates and maintains. Note in particular that each thread has an independent default random number generator (as returned by vl_get_rand). VLFeat objects that involve using random numbers will typically use the random number generator of the thread currently accessing the object (although an object-specific generator can be often be specified instead).
• Any other global function is considered non-thread safe and is accessed exclusively by one thread at a time. A small number of operations are non-reentrant and affect all threads simultaneously. These are restricted to changing certain global configuration parameters, such as the memory allocation functions by vl_set_alloc_func. These operations are not thread safe and are preferably executed before multiple threads start to operate with the library.

# Parallel computations

VLFeat uses OpenMP to implement parallel computations. Generally, this means that multiple cores are uses appropriately and transparently, provided that other multi-threaded parts of the application use OpenMP and that VLFeat and the application link to the same OpenMP library. If finer control is required, read on.

VLFeat functions avoids affecting OpenMP global state, including the desired number of computational threads, in order to minimize side effects to the linked application (e.g. MATLAB). Instead, VLFeat duplicates a few OpenMP control parameters when needed (this approach is similar to the method used by other libraries such as Intel MKL).

The maximum number of threads available to the application can be obtained by vl_get_thread_limit (for OpenMP version 3.0 and greater). This limit is controlled by the OpenMP library (the function is a wrapper around omp_get_thread_limit), which in turn may determined that based on the number of computational cores or the value of the OMP_THREAD_LIMIT variable when the program is launched. This value is an upper bound on the number of computation threads that can be used at any time.

The maximum number of computational thread that VLFeat should use is set by vl_set_num_threads() and retrieved by vl_get_max_threads(). This number is a target value as well as an upper bound to the number of threads used by VLFeat. This value is stored in the VLFeat private state and is not necessarily equal to the corresponding OpenMP state variable retrieved by calling omp_get_max_threads(). vl_set_num_threads(1) disables the use of multiple threads and vl_set_num_threads(0) uses the value returned by the OpenMP call omp_get_max_threads(). The latter value is controlled, for example, by calling omp_set_num_threads() in the application. Note that:

• vl_set_num_threads(0) determines the number of treads using omp_get_max_threads() when it is called. Subsequent calls to omp_set_num_threads() will therefore not affect the number of threads used by VLFeat.
• vl_set_num_threads(vl_get_thread_limit()) causes VLFeat use all the available threads, regardless on the number of threads set within the application by calls to omp_set_num_threads().
• OpenMP may still dynamically decide to use a smaller number of threads in any specific parallel computation.