I have to find what is the fastest way to search the max random number from my array within a range
So I create one method that search normal "using one thread" and another one that use threads
I have Class:MaxThread
import java.util.stream.IntStream;
public class MaxThread extends Thread {
private final int from;
private final int to;
public MaxThread(int[] tab, int from, int to) {
this.from = from;
this.to = to;
}
#Override
public void run() {
long start = System.currentTimeMillis();
int max = IntStream.of(from, to)
.max()
.getAsInt();
long end = System.currentTimeMillis() - start;
System.out.println("Max number from threads is : " + max);
System.out.println("Founded in: " + end + " [ms] ");
}
}
Class: Main2
public class Main2{
public static void main(String[] args) {
int[] tab = new int[200000000];
for (int i = 0; i < tab.length; i++) {
tab[i] = random(0, 200000000);
}
int max = searchMax(0, 50000000);
System.out.println("Max number without using threads " + max);
MaxThread maxThread = new MaxThread(tab, 25000000, 150000000);
maxThread.start();
}
public static int random(int start, int end) {
Random rnd = new Random();
return rnd.nextInt(end - start + 1) + start;
}
public static int searchMax(int from, int to) {
long start = System.currentTimeMillis();
int max = IntStream.of(from, to)
.parallel()
.max()
.getAsInt();
long end = System.currentTimeMillis() - start;
System.out.println("Founded in: " + end + " [ms] ");
return max;
}
}
I count the time in ms inside the method but I want to see witch one was the fastest to find the number , but here is where I cannot find out the way to do it.
Can someone give me and hint please?
Related
I am playing with RecursiveTask of the concurrent package from Java 7. It says this class has an implementation of forkJoin approach and can split my tasks in different threads. So I used a fibonacci example from the Java doc and compared the execution time with a normal recursive fibonacci. And for my surprise the normal recursive took less time! Why? Am I doing anything wrong?
import java.util.concurrent.RecursiveTask;
public class FibonacciJava extends RecursiveTask<Long> {
private static final long serialVersionUID = -2495228492435217747L;
private long n;
protected long valor;
public FibonacciJava(long n) {
this.n = n;
}
#Override
protected Long compute() {
if (n <= 1) {
return n;
}
FibonacciJava f1 = new FibonacciJava(n - 1);
f1.fork();
FibonacciJava f2 = new FibonacciJava(n - 2);
return f2.compute() + f1.join();
}
public long fibonacci(long valor) {
if (valor <= 1)
return valor;
else {
return fibonacci(valor - 1) + fibonacci(valor - 2);
}
}
public static void main(String[] args) {
long value = 40;
FibonacciJava fibonacciJava = new FibonacciJava(value);
long startTimeMillis = System.currentTimeMillis();
System.out.println("RecursiveTask FibonacciJava: "
+ fibonacciJava.compute() + " in "
+ (System.currentTimeMillis() - startTimeMillis)
+ " miliseconds.");
startTimeMillis = System.currentTimeMillis();
System.out.println("Recursive FibonacciJava: "
+ fibonacciJava.fibonacci(value) + " in "
+ (System.currentTimeMillis() - startTimeMillis)
+ " miliseconds.");
}
}
time:
RecursiveTask FibonacciJava: 102334155 in 3681 miliseconds.
Recursive FibonacciJava: 102334155 in 573 miliseconds.
public class Stopwatch {
private double startTime;
private double endTime;
public static void main(String[]args) {
}
public void stopWatch() {
startTime = System.currentTimeMillis();
}
public void start() {
startTime = System.currentTimeMillis();
}
public void stop() {
endTime = System.currentTimeMillis();
}
public long getStartTime()
{
return (long) startTime;
}
public long getEndTime()
{
return (long) endTime;
}
public long getElapsedTime()
{
return (long) (System.currentTimeMillis() - startTime);
}
public short getMilliSeconds()
{
return (short)((System.currentTimeMillis() - startTime) % 1000);
}
}
I need to run this testSearch with the StopWatch Class above
When I input the array size I get the Linear Search result but the Binary Search stays at 0 nano seconds
import java.util.*;
public class testSearch {
public static void main(String[] args){
// input array size from user
Scanner input = new Scanner(System.in);
System.out.print("Enter array size: ");
int size = input.nextInt();
System.out.println();
// create the array (the numbers do not really matter)
int[] numbers = new int[size];
for(int i=0; i<numbers.length; i++){
// we want the numbers sorted for binary search
// so why not just the numbers 0,1,...,size-1
numbers[i]=i;
}
// store the time now
long startTime = System.nanoTime();
// linear search for size (which is not in the array)
linearSearch(numbers,size);
// display the time elapsed
System.out.println("The time taken by Linear Search is " + (System.nanoTime() - startTime) + "nanoseconds.");
// prepare to measure the time elapsed again
startTime = System.nanoTime();
// binary search for size
binarySearch(numbers,size);
// display the time elapsed
System.out.println("The time taken by Binary Search is " + (System.nanoTime() - startTime) + "nanoseconds.");
}
public static boolean linearSearch(int[] a, int key) {
for(int i=0; i<a.length; i++){
if(a[i]==key) return true;
}
return false;
}
public static boolean binarySearch(int[] a, int key) {
int low = 0;
int high = a.length -1;
int mid;
while (low <= high) {
mid = (low + high) / 2;
if (a[mid]>key) {
high = mid - 1;
} else if (a[mid]<key) {
low = mid + 1;
} else {
return true;
}
}
return false;
}
}
Here is the output that I get
Enter array size:
2
The time taken by Linear Search is 1456959922854 milliseconds.
The time taken by Binary Search is 0 milliseconds.
I am trying to write a Fibonacci sequence generator based on Java. I saw many examples on the Internet for instance:
public class Fibonacci {
public static void main(String[] args) {
generateFibonacci(20); // generate the first 20 fibonacci numbers
}
public static void generateFibonacci(long limit) {
long first = 0;
long second = 1;
System.out.print(first+", "+second);
for(long i=1;i<limit;i++) {
long next = first + second;
System.out.print(", "+next);
first = second;
second = next;
}
System.out.println();
}
}
And it works fine. The problem is that not only I want to generate the first 20 numbers, but I also need to specify a starting point. For example:
public List<Long> generateFibonacci(long startFrom, long numberTerms) {
}
Doing:
generateFibonacci(5, 10);
Should output:
8l
13l
21l
34l
55l
89l
144l
233l
377l
I have tried the following code but it doesnt seem to be performing the desired action:
public class example {
public static void main(String[] args) {
generateFibonacci(10, 5);
}
public static void generateFibonacci(long limit, long startPoint) {
long first = 0;
long second = 1;
long endPoint = startPoint + limit;
System.out.print(first + ", " + second);
for (long i = 1; i < endPoint; i++) {
long next = first + second;
if (i > startPoint) {
System.out.print(", " + next);
}
;
System.out.print(", " + next);
first = second;
second = next;
}
}
}
Any ideas on how to achieve this in an efficient way?
as you said output must be like this
8
[13, 21, 34, 55, 89, 144, 233, 377]
and you want to return a list of fibonacci numbers
you can return a list as you want in this way !
public static void main(String[] args) {
List<Long> list = generateFibonacci(10, 5);
System.out.println(list.size());
System.out.println(Arrays.toString(list.toArray()));
}
public static List<Long> generateFibonacci(long limit, long startPoint) {
List<Long> list = new ArrayList<>();
long first = 0;
long second = 1;
long endPoint = startPoint + limit - 1;
//System.out.print(first + ", " + second);
if (startPoint==0){
list.add(0);
list.add(1);
}else if (startPoint ==1){
list.add(1);
}
for (long i = 2; i < endPoint; i++) {
long next = first + second;
if (i > startPoint) {
// System.out.println(next);
list.add(next);
}
first = second;
second = next;
}
return list;
}
Line 10 is always going to print 0 and 1, so remove that.
You have a semi-colon on line 16, and line 17 prints all Fibonacci numbers which is why you get two of the ones you want
Try:
public class example {
public static void main(String[] args) {
generateFibonacci(10, 5);
}
public static void generateFibonacci(long limit, long startPoint) {
long first = 0;
long second = 1;
long endPoint = startPoint + limit;
for (long i = 1; i < endPoint; i++) {
long next = first + second;
if (i == startPoint) {
System.out.print(next);
}
else if ( i > startPoint){
System.out.print(", " + next);
}
first = second;
second = next;
}
}
if (i > startPoint) Here you do not have to put conditions on i but on next.
The problem is that not only I want to generate the first 20 numbers,
but I also need to specify a starting point.
Also, I'm not sure why you are printing the first two elements i.e. 0 and 1. I have removed the sysout() to meet the startPoint condition as you specified.
Here is the corrected code snippet:
public static void generateFibonacci(long limit, long startPoint) {
long first = 0;
long second = 1;
long endPoint = startPoint + limit;
long next = first + second;
for (long i = 1; i < endPoint; i++) {
if (next > startPoint) {
System.out.print(next + ", ");
}
first = second;
second = next;
next = first + second;
}
}
Output:
8, 13, 21, 34, 55, 89, 144, 233, 377, 610
Since you have to calculate the initial Fibonacci numbers anyway, just use the standard method and do this:
public static void generateFibonacci(long limit, long startPoint) {
return generateFibonacci(limit).subList(startPoint - 1, limit);
}
Hey guys I need some help with my homework. I understand the way the Fork and Join Framework works, but my code does not join the results. Our exercise is to write a program, that counts the true values in an array. Sorry for any mistakes (bad grammar or something else) in this post, it is my first one.
Edit:
Thanks for all the requests here is my solution of this problem:
TrueFinder Class:
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
class TrueFinder extends RecursiveTask<TrueResult>
{
private static final int SEQUENTIAL_THRESHOLD = 5;
private boolean[] trueData;
private final int start;
private final int end;
public TrueFinder(boolean[] data, int start, int end)
{
this.trueData = data;
this.start = start;
this.end = end;
}
public TrueFinder(boolean[] data)
{
this(data, 0, data.length);
}
protected TrueResult compute()
{
final int length = end - start;
int counter = 0;
if (length < SEQUENTIAL_THRESHOLD)
{
for (int i = start; i < end; i++)
{
if (trueData[i])
{
counter++;
}
}
return new TrueResult(counter);
}
else
{
final int split = length / 2;
TrueFinder left = new TrueFinder(trueData, start, start + split);
left.fork();
TrueFinder right = new TrueFinder(trueData, start + split, end);
TrueResult subResultRight = right.compute();
TrueResult subResultLeft = left.join();
return new TrueResult(subResultRight.getTrueCounter() +
subResultLeft.getTrueCounter());
}
}
public static void main(String[] args)
{
int trues = 0;
boolean[] trueArray = new boolean[500];
for (int i = 0; i < 500; i++)
{
if (Math.random() < 0.3)
{
trueArray[i] = true;
trues++;
}
else
{
trueArray[i] = false;
}
}
TrueFinder finder = new TrueFinder(trueArray);
ForkJoinPool pool = new ForkJoinPool(4);
long startTime = System.currentTimeMillis();
TrueResult result = pool.invoke(finder);
long endTime = System.currentTimeMillis();
long actualTime = endTime - startTime;
System.out.println("Array mit der Länge " + trueArray.length + " in"
actualTime + " msec dursucht und " + result.getTrueCounter() +
" von " + trues + " True Werten gefunden.");
}
}
And the result class:
public class TrueResult
{
private int trueCounter;
public TrueResult(int counter)
{
this.trueCounter = counter;
}
public int getTrueCounter()
{
return trueCounter;
}
}
The splitting task of your souce code is wrong as :
(1) your splitting isn't started from 0:
your start is 1
(2) fraction point is ignored for your splitting;
(granted that SEQUENTIAL_THRESHOLD=5 and trueArray.length = 13, your splitting is ignoring of the numbers from 11 to 12)
(3) if you modify for (1) and (2), the length of subtasks must be split not SQCUQNTIALTHRESHOLD.
So, the modifying source code is below:
else
{
int split = (length - 1 ) / SEQUENTIAL_THRESHOLD + 1;
TrueFinder[] subtasks = new TrueFinder[split];
int start = 0;
for(int i = 0; i < split - 1; i++)
{
subtasks[i] = new TrueFinder(trueData, start, start + SEQUENTIAL_THRESHOLD);
subtasks[i].fork();
start += SEQUENTIAL_THRESHOLD;
}
subtasks[split - 1] = new TrueFinder(trueData, start, length);
counter = subtasks[split - 1].compute();// better invoking compute than join
for (int i = 0; i < SEQUENTIAL_THRESHOLD; i++)
{
counter += subtasks[i].join();
}
return new TrueResult(counter);
}
I am trying to understand the utilities in java.util.concurrent package and learnt that we can submit callable objects to the ExecutorService, which returns Future, which is filled with the value returned by the callable, after successful completion of task within call() method.
I am understanding that all the callables are executed concurrently using multiple threads.
When I wanted to see how much improvement ExecutorService gives over the batch task execution, i thought of capturing time.
Following is the code which i tried to execute -
package concurrency;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ExecutorExample {
private static Callable<String> callable = new Callable<String>() {
#Override
public String call() throws Exception {
StringBuilder builder = new StringBuilder();
for(int i=0; i<5; i++) {
builder.append(i);
}
return builder.toString();
}
};
public static void main(String [] args) {
long start = System.currentTimeMillis();
ExecutorService service = Executors.newFixedThreadPool(5);
List<Future<String>> futures = new ArrayList<Future<String>>();
for(int i=0; i<5; i++) {
Future<String> value = service.submit(callable);
futures.add(value);
}
for(Future<String> f : futures) {
try {
System.out.println(f.isDone() + " " + f.get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
long end = System.currentTimeMillis();
System.out.println("Executer callable time - " + (end - start));
service.shutdown();
start = System.currentTimeMillis();
for(int i=0; i<5; i++) {
StringBuilder builder = new StringBuilder();
for(int j=0; j<5; j++) {
builder.append(j);
}
System.out.println(builder.toString());
}
end = System.currentTimeMillis();
System.out.println("Normal time - " + (end - start));
}
}
and here is the output of this -
true 01234
true 01234
true 01234
true 01234
true 01234
Executer callable time - 5
01234
01234
01234
01234
01234
Normal time - 0
Please let me know if I am missing something OR understanding something in a wrong way.
Thanks in advance for your time and help for this thread.
If you task in Callable is to small, you won't get benefits from concurrency due task switching and overhead for initialisation. Try to add more heavier loop in callable, say 1000000 iterations, and you can see difference
When you run any code esp for the first time, it takes time. If you pass a task to another thread it can take 1-10 micro-seconds and if your task take less time than this, the overhead can be greater than the benefit. i.e. using multiple threads can be much slower than using a single thread if your overhead is high enough.
I suggest you
increase the cost of the task to 1000 iterations.
make sure the result is not discarded in the single threaded example
run both tests for at least a couple of seconds to ensure the code has warmed up.
Not an answer (but I am not sure the code will fit a comment). To expand a bit on what Peter said, there is usually a sweet spot for the size of your jobs (measured in execution time), to balance pool/queue overhead with fair work distribution among workers. The code example helps find an estimate for that sweet spot. Run on your target hardware.
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
public class FibonacciFork extends RecursiveTask<Long> {
private static final long serialVersionUID = 1L;
public FibonacciFork( long n) {
super();
this.n = n;
}
static ForkJoinPool fjp = new ForkJoinPool( Runtime.getRuntime().availableProcessors());
static long fibonacci0( long n) {
if ( n < 2) {
return n;
}
return fibonacci0( n - 1) + fibonacci0( n - 2);
}
static int rekLimit = 8;
private static long stealCount;
long n;
private long forkCount;
private static AtomicLong forks = new AtomicLong( 0);
public static void main( String[] args) {
int n = 45;
long times[] = getSingleThreadNanos( n);
System.out.println( "Single Thread Times complete");
for ( int r = 2; r <= n; r++) {
runWithRecursionLimit( r, n, times[ r]);
}
}
private static long[] getSingleThreadNanos( int n) {
final long times[] = new long[ n + 1];
ExecutorService es = Executors.newFixedThreadPool( Math.max( 1, Runtime.getRuntime().availableProcessors() / 2));
for ( int i = 2; i <= n; i++) {
final int arg = i;
Runnable runner = new Runnable() {
#Override
public void run() {
long start = System.nanoTime();
final int minRuntime = 1000000000;
long runUntil = start + minRuntime;
long result = fibonacci0( arg);
long end = System.nanoTime();
int ntimes = Math.max( 1, ( int) ( minRuntime / ( end - start)));
if ( ntimes > 1) {
start = System.nanoTime();
for ( int i = 0; i < ntimes; i++) {
result = fibonacci0( arg);
}
end = System.nanoTime();
}
times[ arg] = ( end - start) / ntimes;
}
};
es.execute( runner);
}
es.shutdown();
try {
es.awaitTermination( 1, TimeUnit.HOURS);
} catch ( InterruptedException e) {
System.out.println( "Single Timeout");
}
return times;
}
private static void runWithRecursionLimit( int r, int arg, long singleThreadNanos) {
rekLimit = r;
long start = System.currentTimeMillis();
long result = fibonacci( arg);
long end = System.currentTimeMillis();
// Steals zählen
long currentSteals = fjp.getStealCount();
long newSteals = currentSteals - stealCount;
stealCount = currentSteals;
long forksCount = forks.getAndSet( 0);
System.out.println( "Fib(" + arg + ")=" + result + " in " + ( end-start) + "ms, recursion limit: " + r +
" at " + ( singleThreadNanos / 1e6) + "ms, steals: " + newSteals + " forks " + forksCount);
}
static long fibonacci( final long arg) {
FibonacciFork task = new FibonacciFork( arg);
long result = fjp.invoke( task);
forks.set( task.forkCount);
return result;
}
#Override
protected Long compute() {
if ( n <= rekLimit) {
return fibonacci0( n);
}
FibonacciFork ff1 = new FibonacciFork( n-1);
FibonacciFork ff2 = new FibonacciFork( n-2);
ff1.fork();
long r2 = ff2.compute();
long r1 = ff1.join();
forkCount = ff2.forkCount + ff1.forkCount + 1;
return r1 + r2;
}
}