Correctly parallelising lots of little tasks within a method using C#.NET
I'm implementing image processing algorithms in C# using .NET Framework 4.72 and need to decrease the computation code. Overall the code is sequential but there are quite a few methods with parameters that do not depend on each other. For example, it might be something like this
public void Algorithm(Object x, Object y) {
x = Filter(x);
x = Morphology(x);
y = Filter(y);
y = Morphology(y);
var z = Add(x,y);
//Similar pattern of separate operation that are then combined.
}
These functions generally take around 100ms to 500ms. They can be parallelised, and my approach has been something like this:
public void Algorithm(Object x, Object y) {
var xTask = Task.Run(() => {
x = Filter(x);
x = Morphology(x);
});
var yTask = Task.Run(() => {
y = Filter(y);
y = Morphology(y);
});
Task.WaitAll(xTask, yTask);
var z = Add(x,y);
}
It seems to work, a similar bit of code runs approximately twice as fast. (Note that the whole thing is wrapped in another Task.Run
in the top most level function, so that is why I'm not await
ing here.
Question: Is this a valid approach, or is there another method for parallelising lots of little method calls that is more safe or efficient?
Update: This is not for parallelising processing a batch of images. It is about processing a single image as quick as possible.
c# .net task-parallel-library
add a comment |
I'm implementing image processing algorithms in C# using .NET Framework 4.72 and need to decrease the computation code. Overall the code is sequential but there are quite a few methods with parameters that do not depend on each other. For example, it might be something like this
public void Algorithm(Object x, Object y) {
x = Filter(x);
x = Morphology(x);
y = Filter(y);
y = Morphology(y);
var z = Add(x,y);
//Similar pattern of separate operation that are then combined.
}
These functions generally take around 100ms to 500ms. They can be parallelised, and my approach has been something like this:
public void Algorithm(Object x, Object y) {
var xTask = Task.Run(() => {
x = Filter(x);
x = Morphology(x);
});
var yTask = Task.Run(() => {
y = Filter(y);
y = Morphology(y);
});
Task.WaitAll(xTask, yTask);
var z = Add(x,y);
}
It seems to work, a similar bit of code runs approximately twice as fast. (Note that the whole thing is wrapped in another Task.Run
in the top most level function, so that is why I'm not await
ing here.
Question: Is this a valid approach, or is there another method for parallelising lots of little method calls that is more safe or efficient?
Update: This is not for parallelising processing a batch of images. It is about processing a single image as quick as possible.
c# .net task-parallel-library
try to explore Task.Factory for more detailed task creation. Also try to explore the shared context in tasks. I don't know what x,y,z is. If it is a reference type object then this code is a killer in parallel/multithread programming
– Hassaan
Nov 20 '18 at 17:06
1
Try TPL DataFlow
– Peter Bons
Nov 20 '18 at 17:06
1
Parallel.ForEach( //do stuff )? docs.microsoft.com/en-us/dotnet/standard/parallel-programming/… Literally designed for easy parallel operations :)
– Dan Rayson
Nov 20 '18 at 17:09
@PeterBons Thanks - TPL DataFlow looks interesting.
– geometrikal
Nov 20 '18 at 17:12
add a comment |
I'm implementing image processing algorithms in C# using .NET Framework 4.72 and need to decrease the computation code. Overall the code is sequential but there are quite a few methods with parameters that do not depend on each other. For example, it might be something like this
public void Algorithm(Object x, Object y) {
x = Filter(x);
x = Morphology(x);
y = Filter(y);
y = Morphology(y);
var z = Add(x,y);
//Similar pattern of separate operation that are then combined.
}
These functions generally take around 100ms to 500ms. They can be parallelised, and my approach has been something like this:
public void Algorithm(Object x, Object y) {
var xTask = Task.Run(() => {
x = Filter(x);
x = Morphology(x);
});
var yTask = Task.Run(() => {
y = Filter(y);
y = Morphology(y);
});
Task.WaitAll(xTask, yTask);
var z = Add(x,y);
}
It seems to work, a similar bit of code runs approximately twice as fast. (Note that the whole thing is wrapped in another Task.Run
in the top most level function, so that is why I'm not await
ing here.
Question: Is this a valid approach, or is there another method for parallelising lots of little method calls that is more safe or efficient?
Update: This is not for parallelising processing a batch of images. It is about processing a single image as quick as possible.
c# .net task-parallel-library
I'm implementing image processing algorithms in C# using .NET Framework 4.72 and need to decrease the computation code. Overall the code is sequential but there are quite a few methods with parameters that do not depend on each other. For example, it might be something like this
public void Algorithm(Object x, Object y) {
x = Filter(x);
x = Morphology(x);
y = Filter(y);
y = Morphology(y);
var z = Add(x,y);
//Similar pattern of separate operation that are then combined.
}
These functions generally take around 100ms to 500ms. They can be parallelised, and my approach has been something like this:
public void Algorithm(Object x, Object y) {
var xTask = Task.Run(() => {
x = Filter(x);
x = Morphology(x);
});
var yTask = Task.Run(() => {
y = Filter(y);
y = Morphology(y);
});
Task.WaitAll(xTask, yTask);
var z = Add(x,y);
}
It seems to work, a similar bit of code runs approximately twice as fast. (Note that the whole thing is wrapped in another Task.Run
in the top most level function, so that is why I'm not await
ing here.
Question: Is this a valid approach, or is there another method for parallelising lots of little method calls that is more safe or efficient?
Update: This is not for parallelising processing a batch of images. It is about processing a single image as quick as possible.
c# .net task-parallel-library
c# .net task-parallel-library
edited Nov 20 '18 at 17:16
geometrikal
asked Nov 20 '18 at 16:46


geometrikalgeometrikal
9422927
9422927
try to explore Task.Factory for more detailed task creation. Also try to explore the shared context in tasks. I don't know what x,y,z is. If it is a reference type object then this code is a killer in parallel/multithread programming
– Hassaan
Nov 20 '18 at 17:06
1
Try TPL DataFlow
– Peter Bons
Nov 20 '18 at 17:06
1
Parallel.ForEach( //do stuff )? docs.microsoft.com/en-us/dotnet/standard/parallel-programming/… Literally designed for easy parallel operations :)
– Dan Rayson
Nov 20 '18 at 17:09
@PeterBons Thanks - TPL DataFlow looks interesting.
– geometrikal
Nov 20 '18 at 17:12
add a comment |
try to explore Task.Factory for more detailed task creation. Also try to explore the shared context in tasks. I don't know what x,y,z is. If it is a reference type object then this code is a killer in parallel/multithread programming
– Hassaan
Nov 20 '18 at 17:06
1
Try TPL DataFlow
– Peter Bons
Nov 20 '18 at 17:06
1
Parallel.ForEach( //do stuff )? docs.microsoft.com/en-us/dotnet/standard/parallel-programming/… Literally designed for easy parallel operations :)
– Dan Rayson
Nov 20 '18 at 17:09
@PeterBons Thanks - TPL DataFlow looks interesting.
– geometrikal
Nov 20 '18 at 17:12
try to explore Task.Factory for more detailed task creation. Also try to explore the shared context in tasks. I don't know what x,y,z is. If it is a reference type object then this code is a killer in parallel/multithread programming
– Hassaan
Nov 20 '18 at 17:06
try to explore Task.Factory for more detailed task creation. Also try to explore the shared context in tasks. I don't know what x,y,z is. If it is a reference type object then this code is a killer in parallel/multithread programming
– Hassaan
Nov 20 '18 at 17:06
1
1
Try TPL DataFlow
– Peter Bons
Nov 20 '18 at 17:06
Try TPL DataFlow
– Peter Bons
Nov 20 '18 at 17:06
1
1
Parallel.ForEach( //do stuff )? docs.microsoft.com/en-us/dotnet/standard/parallel-programming/… Literally designed for easy parallel operations :)
– Dan Rayson
Nov 20 '18 at 17:09
Parallel.ForEach( //do stuff )? docs.microsoft.com/en-us/dotnet/standard/parallel-programming/… Literally designed for easy parallel operations :)
– Dan Rayson
Nov 20 '18 at 17:09
@PeterBons Thanks - TPL DataFlow looks interesting.
– geometrikal
Nov 20 '18 at 17:12
@PeterBons Thanks - TPL DataFlow looks interesting.
– geometrikal
Nov 20 '18 at 17:12
add a comment |
1 Answer
1
active
oldest
votes
This is valid enough - if you can process your workload in parallel then you should. You just need to be very aware of WHEN your workload can and should be parallel - and when it needs to be performed in order.
You also need to consider the cost of creating a new task, versus the benefits of doing so (i.e. sometimes avoid very small, very fast tasks).
I would strongly recommend you create additional methods and collections for managing your tasks - when they complete, and handle running lots of separate sets in parallel. Avoiding locking, managing shared memory/variables etc. For example, are you only ever processing one image at a time, or can you start processing the next one if you have cores available?
You need to be very careful with Task.WaitAll() - obviously you need to draw all your work together at some point, but be careful not to lock or block other work.
There's lots of articles out there on the various patterns you can use (pipelines sounds like a good match here).
Here's a few starters:
https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/tpl-and-traditional-async-programming
https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/potential-pitfalls-in-data-and-task-parallelism
When processing a set of images I normally put all the work inParallel.ForEach
etc. In this case, the program interacts with a machine which waits on the result of the image processing before it can continue, so I have to try to parallelise within the method as much as possible.
– geometrikal
Nov 20 '18 at 17:15
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53397708%2fcorrectly-parallelising-lots-of-little-tasks-within-a-method-using-c-net%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
This is valid enough - if you can process your workload in parallel then you should. You just need to be very aware of WHEN your workload can and should be parallel - and when it needs to be performed in order.
You also need to consider the cost of creating a new task, versus the benefits of doing so (i.e. sometimes avoid very small, very fast tasks).
I would strongly recommend you create additional methods and collections for managing your tasks - when they complete, and handle running lots of separate sets in parallel. Avoiding locking, managing shared memory/variables etc. For example, are you only ever processing one image at a time, or can you start processing the next one if you have cores available?
You need to be very careful with Task.WaitAll() - obviously you need to draw all your work together at some point, but be careful not to lock or block other work.
There's lots of articles out there on the various patterns you can use (pipelines sounds like a good match here).
Here's a few starters:
https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/tpl-and-traditional-async-programming
https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/potential-pitfalls-in-data-and-task-parallelism
When processing a set of images I normally put all the work inParallel.ForEach
etc. In this case, the program interacts with a machine which waits on the result of the image processing before it can continue, so I have to try to parallelise within the method as much as possible.
– geometrikal
Nov 20 '18 at 17:15
add a comment |
This is valid enough - if you can process your workload in parallel then you should. You just need to be very aware of WHEN your workload can and should be parallel - and when it needs to be performed in order.
You also need to consider the cost of creating a new task, versus the benefits of doing so (i.e. sometimes avoid very small, very fast tasks).
I would strongly recommend you create additional methods and collections for managing your tasks - when they complete, and handle running lots of separate sets in parallel. Avoiding locking, managing shared memory/variables etc. For example, are you only ever processing one image at a time, or can you start processing the next one if you have cores available?
You need to be very careful with Task.WaitAll() - obviously you need to draw all your work together at some point, but be careful not to lock or block other work.
There's lots of articles out there on the various patterns you can use (pipelines sounds like a good match here).
Here's a few starters:
https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/tpl-and-traditional-async-programming
https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/potential-pitfalls-in-data-and-task-parallelism
When processing a set of images I normally put all the work inParallel.ForEach
etc. In this case, the program interacts with a machine which waits on the result of the image processing before it can continue, so I have to try to parallelise within the method as much as possible.
– geometrikal
Nov 20 '18 at 17:15
add a comment |
This is valid enough - if you can process your workload in parallel then you should. You just need to be very aware of WHEN your workload can and should be parallel - and when it needs to be performed in order.
You also need to consider the cost of creating a new task, versus the benefits of doing so (i.e. sometimes avoid very small, very fast tasks).
I would strongly recommend you create additional methods and collections for managing your tasks - when they complete, and handle running lots of separate sets in parallel. Avoiding locking, managing shared memory/variables etc. For example, are you only ever processing one image at a time, or can you start processing the next one if you have cores available?
You need to be very careful with Task.WaitAll() - obviously you need to draw all your work together at some point, but be careful not to lock or block other work.
There's lots of articles out there on the various patterns you can use (pipelines sounds like a good match here).
Here's a few starters:
https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/tpl-and-traditional-async-programming
https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/potential-pitfalls-in-data-and-task-parallelism
This is valid enough - if you can process your workload in parallel then you should. You just need to be very aware of WHEN your workload can and should be parallel - and when it needs to be performed in order.
You also need to consider the cost of creating a new task, versus the benefits of doing so (i.e. sometimes avoid very small, very fast tasks).
I would strongly recommend you create additional methods and collections for managing your tasks - when they complete, and handle running lots of separate sets in parallel. Avoiding locking, managing shared memory/variables etc. For example, are you only ever processing one image at a time, or can you start processing the next one if you have cores available?
You need to be very careful with Task.WaitAll() - obviously you need to draw all your work together at some point, but be careful not to lock or block other work.
There's lots of articles out there on the various patterns you can use (pipelines sounds like a good match here).
Here's a few starters:
https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/tpl-and-traditional-async-programming
https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/potential-pitfalls-in-data-and-task-parallelism
answered Nov 20 '18 at 17:09
Phil SPhil S
1789
1789
When processing a set of images I normally put all the work inParallel.ForEach
etc. In this case, the program interacts with a machine which waits on the result of the image processing before it can continue, so I have to try to parallelise within the method as much as possible.
– geometrikal
Nov 20 '18 at 17:15
add a comment |
When processing a set of images I normally put all the work inParallel.ForEach
etc. In this case, the program interacts with a machine which waits on the result of the image processing before it can continue, so I have to try to parallelise within the method as much as possible.
– geometrikal
Nov 20 '18 at 17:15
When processing a set of images I normally put all the work in
Parallel.ForEach
etc. In this case, the program interacts with a machine which waits on the result of the image processing before it can continue, so I have to try to parallelise within the method as much as possible.– geometrikal
Nov 20 '18 at 17:15
When processing a set of images I normally put all the work in
Parallel.ForEach
etc. In this case, the program interacts with a machine which waits on the result of the image processing before it can continue, so I have to try to parallelise within the method as much as possible.– geometrikal
Nov 20 '18 at 17:15
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53397708%2fcorrectly-parallelising-lots-of-little-tasks-within-a-method-using-c-net%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
try to explore Task.Factory for more detailed task creation. Also try to explore the shared context in tasks. I don't know what x,y,z is. If it is a reference type object then this code is a killer in parallel/multithread programming
– Hassaan
Nov 20 '18 at 17:06
1
Try TPL DataFlow
– Peter Bons
Nov 20 '18 at 17:06
1
Parallel.ForEach( //do stuff )? docs.microsoft.com/en-us/dotnet/standard/parallel-programming/… Literally designed for easy parallel operations :)
– Dan Rayson
Nov 20 '18 at 17:09
@PeterBons Thanks - TPL DataFlow looks interesting.
– geometrikal
Nov 20 '18 at 17:12