Intel® oneAPI Threading Building Blocks
Ask questions and share information about adding parallelism to your applications when using this threading library.

Tasks that do I/O

christian_convey
Beginner
551 Views

When a TBB task executes a potentially blocking I/O operation (for example, reading a file), will the TBB schedule do something smart to avoid wasting CPU time?

0 Kudos
5 Replies
ARCH_R_Intel
Employee
551 Views
The support for those smarts require OS support that tells the user-space TBB scheduler when a thread has become blocked. We've kicked around notions of trying to do this with OS's that have the support (e.g. User Mode Scheduling in 64-bit Windows 7), but so far have not attempted it. It's essentially as tricky (and as much fun to debug) as writing a kernel-mode scheduler.

If overlapping compute and I/O is important, then perhaps something akin to the "GUI Thread" pattern in the TBB design patterns manual might work, where the GUI thread is replaced by an I/O thread.
0 Kudos
christian_convey
Beginner
551 Views

So basically (in the case of file or network I/O) I create my own thread, and use (something like) a tbb::concurrent_bounded_queue to move data between it and the producer or consumer task?

Or is your point to use the task::enqueue method as a way of kicking off asynchronous work?

Also, if you do mean I should create my own native thread, does TBB expose a platform-neutral thread library?

0 Kudos
jimdempseyatthecove
Honored Contributor III
551 Views
Christian,

The TBB documentation should have a list of classes that are thread-safe using non-TBB threads. Principally you want to know if the class interacts with the TBB thread scheduler. If it does, then assume it is unsafe for use by your non-TBB threads. The tbb::concurrent_bounded_queue may or may not be safe dependent upon which thread may cause the queue to grow or shrink as well as other issues such as a fair lock (or any lock that can cause the current thread to task steal). I haven't looked into this, maybe one of the other regulars can point you to documentation regarding this information. You can roll your own queue relatively easily. A ring buffer is often all that is required (with first fill starting/resuming non-TBB thread dedicated to I/O task).

There are other threading tools that handle I/O tasks. Pardon a plug here, but QuickThread (www.quickthreadprogramming) offers two classes of thread pools: Compute class and I/O class. The compute class is similar to the purpose of TBB thread pool. The I/O class is there specifically for requirements as your own. So there would be little need to create and manageyour own threads. You can have any number of I/O class threads. The compute class tends to work best when limited to the number of logical processors available to the process (default setting).

Jim Dempsey
0 Kudos
ARCH_R_Intel
Employee
551 Views
TBB 3.0 exposes std::thread. It's defined in include/tbb/compat/thread and fairly close to the C++1x draft std::thread. The significant differences are where time units are requred. Our version uses tbb::tick_count::interval_t because we did not want to recreate the C++1x std::chrono facilities. (We had to stop somewhere, or transitive closure would force us to write a full C++1x library :-)

task::enqueue is good way to kick off work that should not run on a user-created thread. For example, you can use TBB's std::thread to create an I/O thread and want a task to run when some I/O action completes. The I/O thread can do the I/O operation and then use task::enqueue to fire off the task.If the I/O thread needs to wait on the task to complete, consider using std::condition_variable to make it wait, which is in include/tbb/compat/condition_variable. That way the I/O thread blocks while it is waiting and does not waste cycles.

The general strategy is to use threads for control flow that is usually blocked, and tasks for control flow that is usually busy. task::enqueue and condition_variable provide ways to transfer control between the two domains.

0 Kudos
christian_convey
Beginner
551 Views

TBB 3.0 exposes std::thread. It's defined in include/tbb/compat/thread and fairly close to the C++1x draft std::thread. The significant differences are where time units are requred. Our version uses tbb::tick_count::interval_t because we did not want to recreate the C++1x std::chrono facilities. (We had to stop somewhere, or transitive closure would force us to write a full C++1x library :-)


That's good to know. Is there decent documentation anywhere about the ways in which TBB's std::thread differs from a fully compatible C++0x std::thread?
0 Kudos
Reply