Rosetta  2020.37
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Public Member Functions | Static Public Member Functions | Private Member Functions | Friends | List of all members
basic::thread_manager::RosettaThreadManager Class Reference

A manager that maintains a threadpool and handles requests for threads for multithreaded execution of functions. This allows multithreading at many different levels in the Rosetta library hierarchy, from job-level parallel execution down to parallel computation of a score, gradient vector, or interaction graph. More...

#include <RosettaThreadManager.hh>

Inheritance diagram for basic::thread_manager::RosettaThreadManager:
Inheritance graph
[legend]

Public Member Functions

void do_work_vector_in_threads (utility::vector1< RosettaThreadFunction > const &vector_of_work, platform::Size const requested_thread_count, RosettaThreadAssignmentInfo &thread_assignment)
 BASIC API THAT SHOULD BE USED IN MOST CIRCUMSTANCES. Given a vector of functions that were bundled with their arguments with std::bind, each of which can be executed in any order and each of which is safe to execute in parallel with any other, run all of these in threads. More...
 
void do_work_vector_in_threads_no_locking (utility::vector1< RosettaThreadFunction > const &vector_of_work, platform::Size const requested_thread_count, RosettaThreadAssignmentInfo &thread_assignment)
 VARIANT BASIC API THAT SHOULD BE USED FOR WORK VECTORS OF NEAR-EQUAL SIZED CHUNKS WHERE THE CHUNKS ARE SMALL. Given a vector of functions that were bundled with their arguments with std::bind, each of which can be executed in any order and each of which is safe to execute in parallel with any other, run all of these in threads. More...
 
void do_multistage_work_vector_in_threads (utility::vector1< utility::vector1< RosettaThreadFunction > > const &multistage_vector_of_work, platform::Size const requested_thread_count, RosettaThreadAssignmentInfo &thread_assignment)
 VARIANT BASIC API THAT SHOULD BE USED WHERE THE BASIC API CAN'T BE USED. Given a vector of vectors of functions that were bundled with their arguments with std::bind, run all of these in threads. In this case, the bundled functions are in groups, where the individual functions within a group can run in any order (and are safe to run concurrently), but the groups must be run sequentially. This is useful when, for example, you have a bunch of calculations to do, and then some finalization tasks to do after the calculations are done, and you don't want to re-request threads. More...
 
void run_function_in_threads (RosettaThreadFunction &function_to_execute, platform::Size const requested_thread_count, RosettaThreadManagerAdvancedAPIKey const &key, RosettaThreadAssignmentInfo &thread_assignment)
 ADVANCED API THAT SHOULD NOT BE USED IN MOST CIRCUMSTANCES. Given a function that was bundled with its arguments with std::bind, run it in many threads. This calls RosettaThreadPool::run_function_in_threads for the already-running thread pool. If the thread pool has not been created, it first creates it by calling create_thread_pool(). IF YOU DECIDE TO USE THE ADVANCED API, YOU MUST: More...
 
platform::Size get_rosetta_thread_index () const
 Get the Rosetta thread index. More...
 
- Public Member Functions inherited from utility::SingletonBase< RosettaThreadManager >
 SingletonBase ()
 public constructor (the derived class must have a private constructor, of course). More...
 

Static Public Member Functions

static platform::Size total_threads ()
 Get the total number of threads that have been launched or will be launched. More...
 
- Static Public Member Functions inherited from utility::SingletonBase< RosettaThreadManager >
static RosettaThreadManager * get_instance ()
 Safely instantiate a singleton class in a (possibly) multithreaded context. More...
 

Private Member Functions

 RosettaThreadManager ()
 Empty constructor. More...
 
 RosettaThreadManager (RosettaThreadManager const &)=delete
 Copy constructor – explicitly deleted. More...
 
RosettaThreadManager operator= (RosettaThreadManager const &)=delete
 Assignment operator – explicitly deleted. More...
 
 ~RosettaThreadManager ()
 Destructor. Non-empty, since threads must be spun down. More...
 

Friends

class utility::SingletonBase< RosettaThreadManager >
 

Detailed Description

A manager that maintains a threadpool and handles requests for threads for multithreaded execution of functions. This allows multithreading at many different levels in the Rosetta library hierarchy, from job-level parallel execution down to parallel computation of a score, gradient vector, or interaction graph.

Note
In single-threaded builds, this object still exists. It accepts vectors of work and executes them directly, in this case.

Constructor & Destructor Documentation

basic::thread_manager::RosettaThreadManager::RosettaThreadManager ( )
private

Empty constructor.

basic::thread_manager::RosettaThreadManager::RosettaThreadManager ( RosettaThreadManager const &  )
privatedelete

Copy constructor – explicitly deleted.

basic::thread_manager::RosettaThreadManager::~RosettaThreadManager ( )
private

Destructor. Non-empty, since threads must be spun down.

Member Function Documentation

void basic::thread_manager::RosettaThreadManager::do_multistage_work_vector_in_threads ( utility::vector1< utility::vector1< RosettaThreadFunction > > const &  multistage_vector_of_work,
platform::Size const  requested_thread_count,
RosettaThreadAssignmentInfo thread_assignment 
)

VARIANT BASIC API THAT SHOULD BE USED WHERE THE BASIC API CAN'T BE USED. Given a vector of vectors of functions that were bundled with their arguments with std::bind, run all of these in threads. In this case, the bundled functions are in groups, where the individual functions within a group can run in any order (and are safe to run concurrently), but the groups must be run sequentially. This is useful when, for example, you have a bunch of calculations to do, and then some finalization tasks to do after the calculations are done, and you don't want to re-request threads.

The bundled functions should be atomistic pieces of work. They should be bundled with their arguments with std::bind, and the arguments should include the place to store output (i.e. they should return void). These functions should not handle any mutexes themselves, but should ensure that they are operating only on memory locations that no other functions in the vector are operating on.

Note
Under the hood, this sets up appropriate mutexes and then calls run_function_in_threads() to do the work. The work is done concurrently in 1 <= actual count <= min( requested thread count, total thread count ) threads. The function blocks until all threads have finished their work, which means that the individual work units should be small, that the longest-running work unit should be short compared to the total runtime, and that the number of work units should be much greater than the number of threads requested.

References debug_assert, basic::options::OptionKeys::frags::j, min(), run_function_in_threads(), runtime_assert_string_msg, amino_acids::size, basic::TR, and basic::Tracer::Warning.

void basic::thread_manager::RosettaThreadManager::do_work_vector_in_threads ( utility::vector1< RosettaThreadFunction > const &  vector_of_work,
platform::Size const  requested_thread_count,
RosettaThreadAssignmentInfo thread_assignment 
)

BASIC API THAT SHOULD BE USED IN MOST CIRCUMSTANCES. Given a vector of functions that were bundled with their arguments with std::bind, each of which can be executed in any order and each of which is safe to execute in parallel with any other, run all of these in threads.

The bundled functions should be atomistic pieces of work. They should be bundled with their arguments with std::bind, and the arguments should include the place to store output (i.e. they should return void). These functions should not handle any mutexes themselves, but should ensure that they are operating only on memory locations that no other functions in the vector are operating on.

Note
Under the hood, this sets up appropriate mutexes and then calls run_function_in_threads() to do the work. The work is done concurrently in 1 <= actual count <= min( requested thread count, total thread count ) threads. The function blocks until all threads have finished their work, which means that the individual work units should be small, that the longest-running work unit should be short compared to the total runtime, and that the number of work units should be much greater than the number of threads requested.

The bundled functions should be atomistic pieces of work. They should be bundled with their arguments with std::bind, and the arguments should include the place to store output (i.e. they should return void). These functions should not handle any mutexes themselves, but should ensure that they are operating only on memory locations that no other functions in the vector are operating on.

References min(), run_function_in_threads(), runtime_assert_string_msg, basic::TR, and basic::Tracer::Warning.

void basic::thread_manager::RosettaThreadManager::do_work_vector_in_threads_no_locking ( utility::vector1< RosettaThreadFunction > const &  vector_of_work,
platform::Size const  requested_thread_count,
RosettaThreadAssignmentInfo thread_assignment 
)

VARIANT BASIC API THAT SHOULD BE USED FOR WORK VECTORS OF NEAR-EQUAL SIZED CHUNKS WHERE THE CHUNKS ARE SMALL. Given a vector of functions that were bundled with their arguments with std::bind, each of which can be executed in any order and each of which is safe to execute in parallel with any other, run all of these in threads.

The bundled functions should be atomistic pieces of work. They should be bundled with their arguments with std::bind, and the arguments should include the place to store output (i.e. they should return void). These functions should not handle any mutexes themselves, but should ensure that they are operating only on memory locations that no other functions in the vector are operating on.

Note
Under the hood, this sets up no mutexes, instead giving each thread a staggered subset of the work in the vector. It calls run_function_in_threads() to do the work. The work is done concurrently in 1 <= actual count <= min( requested thread count, total thread count ) threads. The function blocks until all threads have finished their work, which means that the individual work units should be small, that the longest-running work unit should be short compared to the total runtime, and that the number of work units should be much greater than the number of threads requested. This function works best for cases in which it is known that most of the work in the vector is of equal size (i.e. load-balancing is unlikely to be an issue), and where the overhead of locking mutexes for each job is likely to be comparable in size to the cost of a job (so we want to avoid this overhead).

References min(), run_function_in_threads(), and runtime_assert_string_msg.

platform::Size basic::thread_manager::RosettaThreadManager::get_rosetta_thread_index ( ) const

Get the Rosetta thread index.

References utility::io::oc::cerr, and MAX_THREAD_INDEX_WARNINGS.

RosettaThreadManager basic::thread_manager::RosettaThreadManager::operator= ( RosettaThreadManager const &  )
privatedelete

Assignment operator – explicitly deleted.

void basic::thread_manager::RosettaThreadManager::run_function_in_threads ( RosettaThreadFunction function_to_execute,
platform::Size const  requested_thread_count,
RosettaThreadManagerAdvancedAPIKey const &  key,
RosettaThreadAssignmentInfo thread_assignment 
)

ADVANCED API THAT SHOULD NOT BE USED IN MOST CIRCUMSTANCES. Given a function that was bundled with its arguments with std::bind, run it in many threads. This calls RosettaThreadPool::run_function_in_threads for the already-running thread pool. If the thread pool has not been created, it first creates it by calling create_thread_pool(). IF YOU DECIDE TO USE THE ADVANCED API, YOU MUST:

  1. Pass this function a RosettaThreadManagerAdvancedAPIKey from the calling context. Since the RosettaThreadManagerAdvancedAPIKey class has a private constructor, it can only be created in whitelisted contexts in its friend list, which means that you must:
  2. Add the class that calls this advanced API to the friend list for the RosettaThreadManagerAdvancedAPIKey class. Since this will trigger breakage of the central_class_modification regression test, you must finally:
  3. Justify to the developer community why you must call this interface and not the safer, basic interface (do_work_vector_in_threads) in both the comments in RosettaThreadManagerAdvancedAPIKey's friend list, the comments in the calling class, AND in your pull request description. Andrew Leaver-Fay and Vikram K. Mulligan will both scrutinize this closely. It is highly recommended that before using the run_function_in_threads() function, you first contact Andrew or Vikram and discuss whether it is possible to do what you want to do using the basic API (the do_work_vector_in_threads() function).

The function is assigned to as many threads as the RosettaThreadPool decides to assign it to, always including the thread from which the request originates. It is guaranteed to run in 1 <= actual_thread_count <= requested_thread_count threads. After assigning the function to up to (requsted_thread_count - 1) other threads, the function executes in the current thread, then the current thread blocks until the assigned threads report that they are idle. All of this is handled by the RosettaThreadPool class (or its derived classes, which may have) different logic for assigning thread requests to threads).

Note
A RosettaThreadAssignmentInfo object should be passed in. It will be populated with the number of threads requested, the number actually assigned, the indices of the assigned threads, and a map of system thread ID to Rosetta thread index. The same owning pointer may optionally be provided to the function to execute by the calling function if the function to execute requires access to this information. Note also that the function passed in is responsible for ensuring that it is able to carry out a large block of work, alone or concurrently with many copies of itself in parallel threads, in a threadsafe manner. Finally, note that this function requires a RosettaThreadManagerAdvancedAPIKey, which can only be instantiated by friend classes in the whitelist in the RosettaThreadManagerAdvancedAPIKey class definition. This ensures that only select classes can access the advanced RosettaThreadManager API.

References runtime_assert_string_msg.

Referenced by do_multistage_work_vector_in_threads(), do_work_vector_in_threads(), and do_work_vector_in_threads_no_locking().

static platform::Size basic::thread_manager::RosettaThreadManager::total_threads ( )
inlinestatic

Get the total number of threads that have been launched or will be launched.

This corresponds to the -multithreading:total_threads option, but it does not access the options system repatedly.d

Note
Always returns 1 in the non-threaded build.

References utility::SingletonBase< RosettaThreadManagerInitializationTracker >::get_instance().

Friends And Related Function Documentation


The documentation for this class was generated from the following files: