task reuse (recycle) question

task reuse (recycle) question

This seems like a simple question but I'm having a devil of a time getting the details correct.

What I'd like to do is createatask class, lets call it "FooTask"that I can instantiate and task allocate once, then spawn repeatly (as needed). For example:

struct FooTask: public task {
Data *_dt;
FooTask() { }
void SetData(Data *data) {
_dt = data;
}
task* execute() {
// do stuff with data
}
};

FooTask *tk1 = 0, *tk2 = 0;
void Fooing(Data *data) {
if (tk1 == 0) {
// construct and call task allocate (of some form) on tk1 and tk2
}
if (tl1->state() != task::executing) {
tk1->SetList(data);
tk1->spawn(*tk1); // may not be the correct call/syntax
}
else if (tk2->state() == task::executing) {
tk2->SetList(data);
tk2->spawn(*tk2); // may not be the correct call/syntax
}
else {
// do something else with data
}
}

I've tried various sorts of allocations and recycle_as's but I always end up with some sort of assertion hit. I've pretty much convinced myself that I need to change this to some sort of pipeline or queue, but I'm nowcurious how one would implement this pattern in C++ w/ TBB. Can anyone provide an example or an explaination of my "wrongheadedness"?

Thanks

5 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

TBB offers such features as task recycling and continuation to avoid some of the overhead associated with task scheduling. The goal therefore is to avoid the spawn calls altogether. It's not clear to me how the code presented above attempts to meetsuch a goal, nor what isthe underlying motivation for using TBB. Do you have a particular algorithm for which you're trying to write parallel code? It's hard for me to answer your question about pipelines or queues without having a better idea about what you're really trying to do.

mad
reed:

TBB offers such features as task recycling and continuation to avoid some of the overhead associated with task scheduling. The goal therefore is to avoid the spawn calls altogether. It's not clear to me how the code presented above attempts to meetsuch a goal, nor what isthe underlying motivation for using TBB. Do you have a particular algorithm for which you're trying to write parallel code? It's hard for me to answer your question about pipelines or queues without having a better idea about what you're really trying to do.

Thank you for replying. I should not have brought up the pipelines or queues, I know how to implement the requiredlogic forthose.

I'm really just interested in how to implement simple task reuse.For examplelets say I have five different (independent)database connections open and I want to set up five tasks (one for each connection). I'd like to be able to send thetask some data and let it update the DB as it can. Or perhaps I would want to implement some sort of"lazy" memory free/delete/dispose, where I hand off a pointer and let the(complex) datastructure it pointsto get freed without having to wait around. I suppose it's a producer -consumer sorta thing.I want to call (set data on the object, the start the task), as needed, without incurring the repeatedcost of task and object creation. I'd like to create the object and task once, then reuse it (throw it back into scheduling)when I need to.

TBB tasks are designed to be fast to create, so it'softennot worth the trouble to recycle them. I timed aa simple recursiveparallelism example and it took ~310 clock cycles to create, spawn, run,and destroy each task. Only about ~90 of those cycle are for creating and destroying the task.

There are methods for recycling tasks in TBB, such as task::recycle_as_child_of. Those methods exist primarily to save the overhead of copying user objects associated with the task. E.g., see how task::recycle_as_child_of is used in "tbb/parallel_for.h" to avoid copyingthe user'srange and body objects. The recycling methods target specific idioms.

If you have heavy-weight objects, then the best route may be to make the object separate from the task, and when you need to schedule work involving the object, create and spawn a task with a pointer/reference to the heavy object.

Thanks, I understand better now.

Leave a Comment

Please sign in to add a comment. Not a member? Join today