Java speedup processes / threads
I have a rather big ArrayList.
I have to go through every index, and do a expensive calculation
My first idea to speed it up was by putting it into a thread.
It works, but it is still extremely slow. I tinkered around the calculation, to make it less expensive, but its still to slow. The best solution i came up with is basically this one.
public void calculate(){
calculatePart(0);
calculatePart(1);
}
public void calculatePart(int offset) {
new Thread() {
@Override
public void run() {
int i = offset;
while(arrayList.size() > i) {
//Do the calulation
i +=2;
}
}
}.start();
}
Yet this feels like a lazy, unprofessional solution. That is why I'm asking if there is a cleaner and even faster solution
java multithreading
|
show 1 more comment
I have a rather big ArrayList.
I have to go through every index, and do a expensive calculation
My first idea to speed it up was by putting it into a thread.
It works, but it is still extremely slow. I tinkered around the calculation, to make it less expensive, but its still to slow. The best solution i came up with is basically this one.
public void calculate(){
calculatePart(0);
calculatePart(1);
}
public void calculatePart(int offset) {
new Thread() {
@Override
public void run() {
int i = offset;
while(arrayList.size() > i) {
//Do the calulation
i +=2;
}
}
}.start();
}
Yet this feels like a lazy, unprofessional solution. That is why I'm asking if there is a cleaner and even faster solution
java multithreading
what sort of calculation are you exactly doing? Are you mutating the objects in the list or are you counting something and storing it in a variable?
– Ryotsu
Nov 23 '18 at 14:39
this is not about speed up of your algo but about parallelism; speed up begins with optimizing the algorithm hidden in the "do the calculation", IMHO
– OznOg
Nov 23 '18 at 14:41
Is the "big" calculation on every index of ArrrayList independent of each other? If it is independent, then you can go ahead with parallelizing, and the degree of parallelism can, of course, be greater then two.
– Lavish Kothari
Nov 23 '18 at 14:50
So you made two threads to process in parallel odd and even elements - why do you expect to see it will be much faster? probably it is a little. BTW it depends on how your "do calculation" looks like - if there is no point to pass control to another thread then second thread will take control only after "do calculation" done for one element by first thread...
– Vadim
Nov 23 '18 at 14:51
1
while(arrayList.size() > i) { means you change the size of the arrayList often. This is a very expensive operation.
– Alexei Kaigorodov
Nov 23 '18 at 14:58
|
show 1 more comment
I have a rather big ArrayList.
I have to go through every index, and do a expensive calculation
My first idea to speed it up was by putting it into a thread.
It works, but it is still extremely slow. I tinkered around the calculation, to make it less expensive, but its still to slow. The best solution i came up with is basically this one.
public void calculate(){
calculatePart(0);
calculatePart(1);
}
public void calculatePart(int offset) {
new Thread() {
@Override
public void run() {
int i = offset;
while(arrayList.size() > i) {
//Do the calulation
i +=2;
}
}
}.start();
}
Yet this feels like a lazy, unprofessional solution. That is why I'm asking if there is a cleaner and even faster solution
java multithreading
I have a rather big ArrayList.
I have to go through every index, and do a expensive calculation
My first idea to speed it up was by putting it into a thread.
It works, but it is still extremely slow. I tinkered around the calculation, to make it less expensive, but its still to slow. The best solution i came up with is basically this one.
public void calculate(){
calculatePart(0);
calculatePart(1);
}
public void calculatePart(int offset) {
new Thread() {
@Override
public void run() {
int i = offset;
while(arrayList.size() > i) {
//Do the calulation
i +=2;
}
}
}.start();
}
Yet this feels like a lazy, unprofessional solution. That is why I'm asking if there is a cleaner and even faster solution
java multithreading
java multithreading
edited Nov 23 '18 at 17:04
Panagiotis Kanavos
55.3k483110
55.3k483110
asked Nov 23 '18 at 14:33
TigerdanTigerdan
62
62
what sort of calculation are you exactly doing? Are you mutating the objects in the list or are you counting something and storing it in a variable?
– Ryotsu
Nov 23 '18 at 14:39
this is not about speed up of your algo but about parallelism; speed up begins with optimizing the algorithm hidden in the "do the calculation", IMHO
– OznOg
Nov 23 '18 at 14:41
Is the "big" calculation on every index of ArrrayList independent of each other? If it is independent, then you can go ahead with parallelizing, and the degree of parallelism can, of course, be greater then two.
– Lavish Kothari
Nov 23 '18 at 14:50
So you made two threads to process in parallel odd and even elements - why do you expect to see it will be much faster? probably it is a little. BTW it depends on how your "do calculation" looks like - if there is no point to pass control to another thread then second thread will take control only after "do calculation" done for one element by first thread...
– Vadim
Nov 23 '18 at 14:51
1
while(arrayList.size() > i) { means you change the size of the arrayList often. This is a very expensive operation.
– Alexei Kaigorodov
Nov 23 '18 at 14:58
|
show 1 more comment
what sort of calculation are you exactly doing? Are you mutating the objects in the list or are you counting something and storing it in a variable?
– Ryotsu
Nov 23 '18 at 14:39
this is not about speed up of your algo but about parallelism; speed up begins with optimizing the algorithm hidden in the "do the calculation", IMHO
– OznOg
Nov 23 '18 at 14:41
Is the "big" calculation on every index of ArrrayList independent of each other? If it is independent, then you can go ahead with parallelizing, and the degree of parallelism can, of course, be greater then two.
– Lavish Kothari
Nov 23 '18 at 14:50
So you made two threads to process in parallel odd and even elements - why do you expect to see it will be much faster? probably it is a little. BTW it depends on how your "do calculation" looks like - if there is no point to pass control to another thread then second thread will take control only after "do calculation" done for one element by first thread...
– Vadim
Nov 23 '18 at 14:51
1
while(arrayList.size() > i) { means you change the size of the arrayList often. This is a very expensive operation.
– Alexei Kaigorodov
Nov 23 '18 at 14:58
what sort of calculation are you exactly doing? Are you mutating the objects in the list or are you counting something and storing it in a variable?
– Ryotsu
Nov 23 '18 at 14:39
what sort of calculation are you exactly doing? Are you mutating the objects in the list or are you counting something and storing it in a variable?
– Ryotsu
Nov 23 '18 at 14:39
this is not about speed up of your algo but about parallelism; speed up begins with optimizing the algorithm hidden in the "do the calculation", IMHO
– OznOg
Nov 23 '18 at 14:41
this is not about speed up of your algo but about parallelism; speed up begins with optimizing the algorithm hidden in the "do the calculation", IMHO
– OznOg
Nov 23 '18 at 14:41
Is the "big" calculation on every index of ArrrayList independent of each other? If it is independent, then you can go ahead with parallelizing, and the degree of parallelism can, of course, be greater then two.
– Lavish Kothari
Nov 23 '18 at 14:50
Is the "big" calculation on every index of ArrrayList independent of each other? If it is independent, then you can go ahead with parallelizing, and the degree of parallelism can, of course, be greater then two.
– Lavish Kothari
Nov 23 '18 at 14:50
So you made two threads to process in parallel odd and even elements - why do you expect to see it will be much faster? probably it is a little. BTW it depends on how your "do calculation" looks like - if there is no point to pass control to another thread then second thread will take control only after "do calculation" done for one element by first thread...
– Vadim
Nov 23 '18 at 14:51
So you made two threads to process in parallel odd and even elements - why do you expect to see it will be much faster? probably it is a little. BTW it depends on how your "do calculation" looks like - if there is no point to pass control to another thread then second thread will take control only after "do calculation" done for one element by first thread...
– Vadim
Nov 23 '18 at 14:51
1
1
while(arrayList.size() > i) { means you change the size of the arrayList often. This is a very expensive operation.
– Alexei Kaigorodov
Nov 23 '18 at 14:58
while(arrayList.size() > i) { means you change the size of the arrayList often. This is a very expensive operation.
– Alexei Kaigorodov
Nov 23 '18 at 14:58
|
show 1 more comment
2 Answers
2
active
oldest
votes
High theoretically speaking:
if you have X elements and your calculation must perform N operations on each one then
your computer(processor) must perform X*N operations total, then...
Parallel threads can make it faster only if in the calculation operations there are some of them when thread is waiting (e.g. File or Network operations). That time can be used by other threads. But if all operations are pure CPU (e.g. mathematics) and thread is not waiting - required time to perform X*N operations stays the same.
Also each tread must give other threads ability to take control over CPU at some point. It happens automatically between methods calls or if you have Thread.yield()
call in your code.
as example method like:
public void run()
{
long a=0;
for (long i=1; i < Long.MAX_VALUE; i++)
{
a+=i;
}
}
will not give other thread a chance to take control over CPU until it fully completed and exited.
True for a single processor, but present day CPUs have multiple processors and thus can handle multiple tasks at the same time, which reduces the total execution time.
– uneq95
Nov 24 '18 at 23:52
From Java prospective it does not matter. Multi-processors/cores handle by OS not by JVM. JVM is nothing else but another process in OS
– Vadim
Nov 26 '18 at 14:59
What do you mean, java can't create threads and get them to do tasks in parallel? What I meant to say was that doing tasks in parallel will reduce the effective time to process all elements, however the work will always remain the same. You have assumed, in your answer, that we only have one processor. What am I missing here?
– uneq95
Nov 27 '18 at 12:19
add a comment |
Assuming that doing task on each element doesn't lead to data races, you could leverage the power of parallelism. To maximize the number of computations occurring at the same time, you would have to give tasks to each of the processors available in your system.
In Java, you can get the number of processors (cores) available using this:
int parallelism = Runtime.getRuntime().availableProcessors();
The idea is to create number of threads equal to the available processors.
So, if you have 4 processors available, you can create 4 threads and ask them to process items at a gap of 4.Suppose you have a list of size 10, which needs to be processed in parallel.
Then,
Thread 1 processes items at index 0,4,8
Thread 2 processes items at index 1,5,9
Thread 3 processes items at index 2,6
Thread 4 processes items at index 3,7
I tried to simulate your scenario with the following code:
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class SpeedUpTest {
public static void main(String args) throws InterruptedException, ExecutionException {
long seqTime, twoThreadTime, multiThreadTime;
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
long time = System.currentTimeMillis();
sequentialProcessing(list);
seqTime = System.currentTimeMillis() - time;
int parallelism = 2;
ExecutorService executorService = Executors.newFixedThreadPool(parallelism);
time = System.currentTimeMillis();
List<Future> tasks = new ArrayList<>();
for (int offset = 0; offset < parallelism; offset++) {
int finalParallelism = parallelism;
int finalOffset = offset;
Future task = executorService.submit(() -> {
int i = finalOffset;
while (list.size() > i) {
try {
processItem(list.get(i));
} catch (InterruptedException e) {
e.printStackTrace();
}
i += finalParallelism;
}
});
tasks.add(task);
}
for (Future task : tasks) {
task.get();
}
twoThreadTime = System.currentTimeMillis() - time;
parallelism = Runtime.getRuntime().availableProcessors();
executorService = Executors.newFixedThreadPool(parallelism);
tasks = new ArrayList<>();
time = System.currentTimeMillis();
for (int offset = 0; offset < parallelism; offset++) {
int finalParallelism = parallelism;
int finalOffset = offset;
Future task = executorService.submit(() -> {
int i = finalOffset;
while (list.size() > i) {
try {
processItem(list.get(i));
} catch (InterruptedException e) {
e.printStackTrace();
}
i += finalParallelism;
}
});
tasks.add(task);
}
for (Future task : tasks) {
task.get();
}
multiThreadTime = System.currentTimeMillis() - time;
log("RESULTS:");
log("Total time for sequential execution : " + seqTime / 1000.0 + " seconds");
log("Total time for execution with 2 threads: " + twoThreadTime / 1000.0 + " seconds");
log("Total time for execution with " + parallelism + " threads: " + multiThreadTime / 1000.0 + " seconds");
}
private static void log(String msg) {
System.out.println(msg);
}
private static void processItem(int index) throws InterruptedException {
Thread.sleep(5000);
}
private static void sequentialProcessing(List<Integer> list) throws InterruptedException {
for (int i = 0; i < list.size(); i++) {
processItem(list.get(i));
}
}
}
OUTPUT:
RESULTS:
Total time for sequential execution : 50.001 seconds
Total time for execution with 2 threads: 25.102 seconds
Total time for execution with 4 threads: 15.002 seconds
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%2f53448577%2fjava-speedup-processes-threads%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
High theoretically speaking:
if you have X elements and your calculation must perform N operations on each one then
your computer(processor) must perform X*N operations total, then...
Parallel threads can make it faster only if in the calculation operations there are some of them when thread is waiting (e.g. File or Network operations). That time can be used by other threads. But if all operations are pure CPU (e.g. mathematics) and thread is not waiting - required time to perform X*N operations stays the same.
Also each tread must give other threads ability to take control over CPU at some point. It happens automatically between methods calls or if you have Thread.yield()
call in your code.
as example method like:
public void run()
{
long a=0;
for (long i=1; i < Long.MAX_VALUE; i++)
{
a+=i;
}
}
will not give other thread a chance to take control over CPU until it fully completed and exited.
True for a single processor, but present day CPUs have multiple processors and thus can handle multiple tasks at the same time, which reduces the total execution time.
– uneq95
Nov 24 '18 at 23:52
From Java prospective it does not matter. Multi-processors/cores handle by OS not by JVM. JVM is nothing else but another process in OS
– Vadim
Nov 26 '18 at 14:59
What do you mean, java can't create threads and get them to do tasks in parallel? What I meant to say was that doing tasks in parallel will reduce the effective time to process all elements, however the work will always remain the same. You have assumed, in your answer, that we only have one processor. What am I missing here?
– uneq95
Nov 27 '18 at 12:19
add a comment |
High theoretically speaking:
if you have X elements and your calculation must perform N operations on each one then
your computer(processor) must perform X*N operations total, then...
Parallel threads can make it faster only if in the calculation operations there are some of them when thread is waiting (e.g. File or Network operations). That time can be used by other threads. But if all operations are pure CPU (e.g. mathematics) and thread is not waiting - required time to perform X*N operations stays the same.
Also each tread must give other threads ability to take control over CPU at some point. It happens automatically between methods calls or if you have Thread.yield()
call in your code.
as example method like:
public void run()
{
long a=0;
for (long i=1; i < Long.MAX_VALUE; i++)
{
a+=i;
}
}
will not give other thread a chance to take control over CPU until it fully completed and exited.
True for a single processor, but present day CPUs have multiple processors and thus can handle multiple tasks at the same time, which reduces the total execution time.
– uneq95
Nov 24 '18 at 23:52
From Java prospective it does not matter. Multi-processors/cores handle by OS not by JVM. JVM is nothing else but another process in OS
– Vadim
Nov 26 '18 at 14:59
What do you mean, java can't create threads and get them to do tasks in parallel? What I meant to say was that doing tasks in parallel will reduce the effective time to process all elements, however the work will always remain the same. You have assumed, in your answer, that we only have one processor. What am I missing here?
– uneq95
Nov 27 '18 at 12:19
add a comment |
High theoretically speaking:
if you have X elements and your calculation must perform N operations on each one then
your computer(processor) must perform X*N operations total, then...
Parallel threads can make it faster only if in the calculation operations there are some of them when thread is waiting (e.g. File or Network operations). That time can be used by other threads. But if all operations are pure CPU (e.g. mathematics) and thread is not waiting - required time to perform X*N operations stays the same.
Also each tread must give other threads ability to take control over CPU at some point. It happens automatically between methods calls or if you have Thread.yield()
call in your code.
as example method like:
public void run()
{
long a=0;
for (long i=1; i < Long.MAX_VALUE; i++)
{
a+=i;
}
}
will not give other thread a chance to take control over CPU until it fully completed and exited.
High theoretically speaking:
if you have X elements and your calculation must perform N operations on each one then
your computer(processor) must perform X*N operations total, then...
Parallel threads can make it faster only if in the calculation operations there are some of them when thread is waiting (e.g. File or Network operations). That time can be used by other threads. But if all operations are pure CPU (e.g. mathematics) and thread is not waiting - required time to perform X*N operations stays the same.
Also each tread must give other threads ability to take control over CPU at some point. It happens automatically between methods calls or if you have Thread.yield()
call in your code.
as example method like:
public void run()
{
long a=0;
for (long i=1; i < Long.MAX_VALUE; i++)
{
a+=i;
}
}
will not give other thread a chance to take control over CPU until it fully completed and exited.
answered Nov 23 '18 at 15:18
VadimVadim
3,4462622
3,4462622
True for a single processor, but present day CPUs have multiple processors and thus can handle multiple tasks at the same time, which reduces the total execution time.
– uneq95
Nov 24 '18 at 23:52
From Java prospective it does not matter. Multi-processors/cores handle by OS not by JVM. JVM is nothing else but another process in OS
– Vadim
Nov 26 '18 at 14:59
What do you mean, java can't create threads and get them to do tasks in parallel? What I meant to say was that doing tasks in parallel will reduce the effective time to process all elements, however the work will always remain the same. You have assumed, in your answer, that we only have one processor. What am I missing here?
– uneq95
Nov 27 '18 at 12:19
add a comment |
True for a single processor, but present day CPUs have multiple processors and thus can handle multiple tasks at the same time, which reduces the total execution time.
– uneq95
Nov 24 '18 at 23:52
From Java prospective it does not matter. Multi-processors/cores handle by OS not by JVM. JVM is nothing else but another process in OS
– Vadim
Nov 26 '18 at 14:59
What do you mean, java can't create threads and get them to do tasks in parallel? What I meant to say was that doing tasks in parallel will reduce the effective time to process all elements, however the work will always remain the same. You have assumed, in your answer, that we only have one processor. What am I missing here?
– uneq95
Nov 27 '18 at 12:19
True for a single processor, but present day CPUs have multiple processors and thus can handle multiple tasks at the same time, which reduces the total execution time.
– uneq95
Nov 24 '18 at 23:52
True for a single processor, but present day CPUs have multiple processors and thus can handle multiple tasks at the same time, which reduces the total execution time.
– uneq95
Nov 24 '18 at 23:52
From Java prospective it does not matter. Multi-processors/cores handle by OS not by JVM. JVM is nothing else but another process in OS
– Vadim
Nov 26 '18 at 14:59
From Java prospective it does not matter. Multi-processors/cores handle by OS not by JVM. JVM is nothing else but another process in OS
– Vadim
Nov 26 '18 at 14:59
What do you mean, java can't create threads and get them to do tasks in parallel? What I meant to say was that doing tasks in parallel will reduce the effective time to process all elements, however the work will always remain the same. You have assumed, in your answer, that we only have one processor. What am I missing here?
– uneq95
Nov 27 '18 at 12:19
What do you mean, java can't create threads and get them to do tasks in parallel? What I meant to say was that doing tasks in parallel will reduce the effective time to process all elements, however the work will always remain the same. You have assumed, in your answer, that we only have one processor. What am I missing here?
– uneq95
Nov 27 '18 at 12:19
add a comment |
Assuming that doing task on each element doesn't lead to data races, you could leverage the power of parallelism. To maximize the number of computations occurring at the same time, you would have to give tasks to each of the processors available in your system.
In Java, you can get the number of processors (cores) available using this:
int parallelism = Runtime.getRuntime().availableProcessors();
The idea is to create number of threads equal to the available processors.
So, if you have 4 processors available, you can create 4 threads and ask them to process items at a gap of 4.Suppose you have a list of size 10, which needs to be processed in parallel.
Then,
Thread 1 processes items at index 0,4,8
Thread 2 processes items at index 1,5,9
Thread 3 processes items at index 2,6
Thread 4 processes items at index 3,7
I tried to simulate your scenario with the following code:
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class SpeedUpTest {
public static void main(String args) throws InterruptedException, ExecutionException {
long seqTime, twoThreadTime, multiThreadTime;
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
long time = System.currentTimeMillis();
sequentialProcessing(list);
seqTime = System.currentTimeMillis() - time;
int parallelism = 2;
ExecutorService executorService = Executors.newFixedThreadPool(parallelism);
time = System.currentTimeMillis();
List<Future> tasks = new ArrayList<>();
for (int offset = 0; offset < parallelism; offset++) {
int finalParallelism = parallelism;
int finalOffset = offset;
Future task = executorService.submit(() -> {
int i = finalOffset;
while (list.size() > i) {
try {
processItem(list.get(i));
} catch (InterruptedException e) {
e.printStackTrace();
}
i += finalParallelism;
}
});
tasks.add(task);
}
for (Future task : tasks) {
task.get();
}
twoThreadTime = System.currentTimeMillis() - time;
parallelism = Runtime.getRuntime().availableProcessors();
executorService = Executors.newFixedThreadPool(parallelism);
tasks = new ArrayList<>();
time = System.currentTimeMillis();
for (int offset = 0; offset < parallelism; offset++) {
int finalParallelism = parallelism;
int finalOffset = offset;
Future task = executorService.submit(() -> {
int i = finalOffset;
while (list.size() > i) {
try {
processItem(list.get(i));
} catch (InterruptedException e) {
e.printStackTrace();
}
i += finalParallelism;
}
});
tasks.add(task);
}
for (Future task : tasks) {
task.get();
}
multiThreadTime = System.currentTimeMillis() - time;
log("RESULTS:");
log("Total time for sequential execution : " + seqTime / 1000.0 + " seconds");
log("Total time for execution with 2 threads: " + twoThreadTime / 1000.0 + " seconds");
log("Total time for execution with " + parallelism + " threads: " + multiThreadTime / 1000.0 + " seconds");
}
private static void log(String msg) {
System.out.println(msg);
}
private static void processItem(int index) throws InterruptedException {
Thread.sleep(5000);
}
private static void sequentialProcessing(List<Integer> list) throws InterruptedException {
for (int i = 0; i < list.size(); i++) {
processItem(list.get(i));
}
}
}
OUTPUT:
RESULTS:
Total time for sequential execution : 50.001 seconds
Total time for execution with 2 threads: 25.102 seconds
Total time for execution with 4 threads: 15.002 seconds
add a comment |
Assuming that doing task on each element doesn't lead to data races, you could leverage the power of parallelism. To maximize the number of computations occurring at the same time, you would have to give tasks to each of the processors available in your system.
In Java, you can get the number of processors (cores) available using this:
int parallelism = Runtime.getRuntime().availableProcessors();
The idea is to create number of threads equal to the available processors.
So, if you have 4 processors available, you can create 4 threads and ask them to process items at a gap of 4.Suppose you have a list of size 10, which needs to be processed in parallel.
Then,
Thread 1 processes items at index 0,4,8
Thread 2 processes items at index 1,5,9
Thread 3 processes items at index 2,6
Thread 4 processes items at index 3,7
I tried to simulate your scenario with the following code:
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class SpeedUpTest {
public static void main(String args) throws InterruptedException, ExecutionException {
long seqTime, twoThreadTime, multiThreadTime;
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
long time = System.currentTimeMillis();
sequentialProcessing(list);
seqTime = System.currentTimeMillis() - time;
int parallelism = 2;
ExecutorService executorService = Executors.newFixedThreadPool(parallelism);
time = System.currentTimeMillis();
List<Future> tasks = new ArrayList<>();
for (int offset = 0; offset < parallelism; offset++) {
int finalParallelism = parallelism;
int finalOffset = offset;
Future task = executorService.submit(() -> {
int i = finalOffset;
while (list.size() > i) {
try {
processItem(list.get(i));
} catch (InterruptedException e) {
e.printStackTrace();
}
i += finalParallelism;
}
});
tasks.add(task);
}
for (Future task : tasks) {
task.get();
}
twoThreadTime = System.currentTimeMillis() - time;
parallelism = Runtime.getRuntime().availableProcessors();
executorService = Executors.newFixedThreadPool(parallelism);
tasks = new ArrayList<>();
time = System.currentTimeMillis();
for (int offset = 0; offset < parallelism; offset++) {
int finalParallelism = parallelism;
int finalOffset = offset;
Future task = executorService.submit(() -> {
int i = finalOffset;
while (list.size() > i) {
try {
processItem(list.get(i));
} catch (InterruptedException e) {
e.printStackTrace();
}
i += finalParallelism;
}
});
tasks.add(task);
}
for (Future task : tasks) {
task.get();
}
multiThreadTime = System.currentTimeMillis() - time;
log("RESULTS:");
log("Total time for sequential execution : " + seqTime / 1000.0 + " seconds");
log("Total time for execution with 2 threads: " + twoThreadTime / 1000.0 + " seconds");
log("Total time for execution with " + parallelism + " threads: " + multiThreadTime / 1000.0 + " seconds");
}
private static void log(String msg) {
System.out.println(msg);
}
private static void processItem(int index) throws InterruptedException {
Thread.sleep(5000);
}
private static void sequentialProcessing(List<Integer> list) throws InterruptedException {
for (int i = 0; i < list.size(); i++) {
processItem(list.get(i));
}
}
}
OUTPUT:
RESULTS:
Total time for sequential execution : 50.001 seconds
Total time for execution with 2 threads: 25.102 seconds
Total time for execution with 4 threads: 15.002 seconds
add a comment |
Assuming that doing task on each element doesn't lead to data races, you could leverage the power of parallelism. To maximize the number of computations occurring at the same time, you would have to give tasks to each of the processors available in your system.
In Java, you can get the number of processors (cores) available using this:
int parallelism = Runtime.getRuntime().availableProcessors();
The idea is to create number of threads equal to the available processors.
So, if you have 4 processors available, you can create 4 threads and ask them to process items at a gap of 4.Suppose you have a list of size 10, which needs to be processed in parallel.
Then,
Thread 1 processes items at index 0,4,8
Thread 2 processes items at index 1,5,9
Thread 3 processes items at index 2,6
Thread 4 processes items at index 3,7
I tried to simulate your scenario with the following code:
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class SpeedUpTest {
public static void main(String args) throws InterruptedException, ExecutionException {
long seqTime, twoThreadTime, multiThreadTime;
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
long time = System.currentTimeMillis();
sequentialProcessing(list);
seqTime = System.currentTimeMillis() - time;
int parallelism = 2;
ExecutorService executorService = Executors.newFixedThreadPool(parallelism);
time = System.currentTimeMillis();
List<Future> tasks = new ArrayList<>();
for (int offset = 0; offset < parallelism; offset++) {
int finalParallelism = parallelism;
int finalOffset = offset;
Future task = executorService.submit(() -> {
int i = finalOffset;
while (list.size() > i) {
try {
processItem(list.get(i));
} catch (InterruptedException e) {
e.printStackTrace();
}
i += finalParallelism;
}
});
tasks.add(task);
}
for (Future task : tasks) {
task.get();
}
twoThreadTime = System.currentTimeMillis() - time;
parallelism = Runtime.getRuntime().availableProcessors();
executorService = Executors.newFixedThreadPool(parallelism);
tasks = new ArrayList<>();
time = System.currentTimeMillis();
for (int offset = 0; offset < parallelism; offset++) {
int finalParallelism = parallelism;
int finalOffset = offset;
Future task = executorService.submit(() -> {
int i = finalOffset;
while (list.size() > i) {
try {
processItem(list.get(i));
} catch (InterruptedException e) {
e.printStackTrace();
}
i += finalParallelism;
}
});
tasks.add(task);
}
for (Future task : tasks) {
task.get();
}
multiThreadTime = System.currentTimeMillis() - time;
log("RESULTS:");
log("Total time for sequential execution : " + seqTime / 1000.0 + " seconds");
log("Total time for execution with 2 threads: " + twoThreadTime / 1000.0 + " seconds");
log("Total time for execution with " + parallelism + " threads: " + multiThreadTime / 1000.0 + " seconds");
}
private static void log(String msg) {
System.out.println(msg);
}
private static void processItem(int index) throws InterruptedException {
Thread.sleep(5000);
}
private static void sequentialProcessing(List<Integer> list) throws InterruptedException {
for (int i = 0; i < list.size(); i++) {
processItem(list.get(i));
}
}
}
OUTPUT:
RESULTS:
Total time for sequential execution : 50.001 seconds
Total time for execution with 2 threads: 25.102 seconds
Total time for execution with 4 threads: 15.002 seconds
Assuming that doing task on each element doesn't lead to data races, you could leverage the power of parallelism. To maximize the number of computations occurring at the same time, you would have to give tasks to each of the processors available in your system.
In Java, you can get the number of processors (cores) available using this:
int parallelism = Runtime.getRuntime().availableProcessors();
The idea is to create number of threads equal to the available processors.
So, if you have 4 processors available, you can create 4 threads and ask them to process items at a gap of 4.Suppose you have a list of size 10, which needs to be processed in parallel.
Then,
Thread 1 processes items at index 0,4,8
Thread 2 processes items at index 1,5,9
Thread 3 processes items at index 2,6
Thread 4 processes items at index 3,7
I tried to simulate your scenario with the following code:
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class SpeedUpTest {
public static void main(String args) throws InterruptedException, ExecutionException {
long seqTime, twoThreadTime, multiThreadTime;
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
long time = System.currentTimeMillis();
sequentialProcessing(list);
seqTime = System.currentTimeMillis() - time;
int parallelism = 2;
ExecutorService executorService = Executors.newFixedThreadPool(parallelism);
time = System.currentTimeMillis();
List<Future> tasks = new ArrayList<>();
for (int offset = 0; offset < parallelism; offset++) {
int finalParallelism = parallelism;
int finalOffset = offset;
Future task = executorService.submit(() -> {
int i = finalOffset;
while (list.size() > i) {
try {
processItem(list.get(i));
} catch (InterruptedException e) {
e.printStackTrace();
}
i += finalParallelism;
}
});
tasks.add(task);
}
for (Future task : tasks) {
task.get();
}
twoThreadTime = System.currentTimeMillis() - time;
parallelism = Runtime.getRuntime().availableProcessors();
executorService = Executors.newFixedThreadPool(parallelism);
tasks = new ArrayList<>();
time = System.currentTimeMillis();
for (int offset = 0; offset < parallelism; offset++) {
int finalParallelism = parallelism;
int finalOffset = offset;
Future task = executorService.submit(() -> {
int i = finalOffset;
while (list.size() > i) {
try {
processItem(list.get(i));
} catch (InterruptedException e) {
e.printStackTrace();
}
i += finalParallelism;
}
});
tasks.add(task);
}
for (Future task : tasks) {
task.get();
}
multiThreadTime = System.currentTimeMillis() - time;
log("RESULTS:");
log("Total time for sequential execution : " + seqTime / 1000.0 + " seconds");
log("Total time for execution with 2 threads: " + twoThreadTime / 1000.0 + " seconds");
log("Total time for execution with " + parallelism + " threads: " + multiThreadTime / 1000.0 + " seconds");
}
private static void log(String msg) {
System.out.println(msg);
}
private static void processItem(int index) throws InterruptedException {
Thread.sleep(5000);
}
private static void sequentialProcessing(List<Integer> list) throws InterruptedException {
for (int i = 0; i < list.size(); i++) {
processItem(list.get(i));
}
}
}
OUTPUT:
RESULTS:
Total time for sequential execution : 50.001 seconds
Total time for execution with 2 threads: 25.102 seconds
Total time for execution with 4 threads: 15.002 seconds
answered Nov 24 '18 at 23:23
uneq95uneq95
863616
863616
add a comment |
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%2f53448577%2fjava-speedup-processes-threads%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
what sort of calculation are you exactly doing? Are you mutating the objects in the list or are you counting something and storing it in a variable?
– Ryotsu
Nov 23 '18 at 14:39
this is not about speed up of your algo but about parallelism; speed up begins with optimizing the algorithm hidden in the "do the calculation", IMHO
– OznOg
Nov 23 '18 at 14:41
Is the "big" calculation on every index of ArrrayList independent of each other? If it is independent, then you can go ahead with parallelizing, and the degree of parallelism can, of course, be greater then two.
– Lavish Kothari
Nov 23 '18 at 14:50
So you made two threads to process in parallel odd and even elements - why do you expect to see it will be much faster? probably it is a little. BTW it depends on how your "do calculation" looks like - if there is no point to pass control to another thread then second thread will take control only after "do calculation" done for one element by first thread...
– Vadim
Nov 23 '18 at 14:51
1
while(arrayList.size() > i) { means you change the size of the arrayList often. This is a very expensive operation.
– Alexei Kaigorodov
Nov 23 '18 at 14:58