0

This program takes input files sequentially but all tasks execute in parallel using a single core. The execution time for all tasks is longer than sequential execution time. I want to reduce the execution time using multiple cores by executing the tasks in parallel. How can I do that? How can I use multi-core in this program? I want to use at least two cores.

package TestParallel;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

/**
 *
 * @author Sohel Rana
 */
public class Executor {

    public void encrypt(File fname) throws Exception {
        System.out.println("Encryption Started : " + System.currentTimeMillis() + " File Name : " + fname);
        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        keyGen.init(256);  //using AES-256
        SecretKey key = keyGen.generateKey();  //generating key
        //  System.out.println("Key = " + bytesToHex(key.getEncoded()));
        Cipher aesCipher = Cipher.getInstance("AES");  //getting cipher for AES
        aesCipher.init(Cipher.ENCRYPT_MODE, key);  //initializing cipher for encryption with key

        //creating file output stream to write to file
        try (FileOutputStream fos = new FileOutputStream(fname + ".aes")) {
            //creating object output stream to write objects to file
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(key);  //saving key to file for use during decryption

            //creating file input stream to read contents for encryption
            try (FileInputStream fis = new FileInputStream(fname)) {
                //creating cipher output stream to write encrypted contents
                try (CipherOutputStream cos = new CipherOutputStream(fos, aesCipher)) {
                    int read;
                    byte buf[] = new byte[4096];
                    while ((read = fis.read(buf)) != -1) //reading from file
                    {
                        cos.write(buf, 0, read);  //encrypting and writing to file
                    }
                }
            }
            System.out.print("\nComplete Time = " + System.currentTimeMillis());
            System.out.println(" \tand file task complete :" + fname);
            //  fname.delete();
        }

    }

    public static void main(final String[] args) throws InterruptedException {
        // final ExecutorService pool = Executors.newFixedThreadPool(4);
        int cores = Runtime.getRuntime().availableProcessors();
        System.out.println("Available processor cores is " + cores);
        File file1 = new File("C:\\Users\\Sohel Rana\\Desktop\\test\\Khushnuma Official Video HD - Suyyash Rai & Kishwer Merchant_HD.mp4");
        File file2 = new File("C:\\Users\\Sohel Rana\\Desktop\\test\\EK MULAQAT - Sonali Cable HD.mp4");
        File file3 = new File("C:\\Users\\Sohel Rana\\Desktop\\test\\Java Cryptography Tutorials 1 AES Encryption and Decryption using Java.mp4");
        File file4 = new File("C:\\Users\\Sohel Rana\\Desktop\\test\\01. Nath Nath.MP4");

        Executor ex = new Executor();
        final ExecutorService executor = Executors.newFixedThreadPool(cores);
        long startTime = System.currentTimeMillis();
        for (File f : new File[]{file1, file2, file3, file4}) {
            startTime = System.currentTimeMillis();
            executor.execute(() -> {
                try {
                    ex.encrypt(f);
                    //System.out.println(f);
                } catch (Exception ex1) {
                    Logger.getLogger(Executor.class.getName()).log(Level.SEVERE, null, ex1);

                }
            });
        }

        executor.shutdown();

        if (executor.awaitTermination(1, TimeUnit.DAYS)) {
        } else {
            executor.shutdownNow();
        }
        long endTime = System.currentTimeMillis();

        System.out.println("\nParalle Execution Time : " + (endTime - startTime)
                + " milliseconds.");

    }
}
rghome
  • 8,529
  • 8
  • 43
  • 62
Sohel
  • 41
  • 4
  • What is not working in your code? – Shanu Gupta Apr 25 '18 at 11:16
  • First it depends on your hardware, for which hardware this code has been compiled ? Does this hardware have at least 2 cores ? – vincrichaud Apr 25 '18 at 11:16
  • You mean multi-threading. Just create a new thread – Niza Siwale Apr 25 '18 at 11:18
  • My code work fine on sigle core. I want use two core for runnig fast.what can I get maximum response from cpu.that's means when run the code, the cpu performance will be 100%. How can do that? – Sohel Apr 25 '18 at 11:20
  • Profile your code to see where is the waiting happening... You are using very large units of work per worker thread - i.e. entire mp4 files, while each worker depends heavily on I/O by reading 4kB at the time... that's very chatty I/O access and my guess (but measure before acting) is that all threads spend a lot of time waiting on I/O. Try reading 40kB or 400kB at the time and see how it will change the time. You could use `Executors.workStealingPool(cores)` but to reap benefits, you work items would have to be much smaller than whole file (maybe size of the buffer). – diginoise Apr 25 '18 at 11:26
  • If you want parallel programming, then you have to use a native language like C++. In Java what's only available is multi threading. Judging from your code, multi thread will not speed up the processing that much – Niza Siwale Apr 25 '18 at 11:26
  • Have a look [here](https://stackoverflow.com/a/3330440/5914654), [there](https://stackoverflow.com/questions/28573180/java-8-automatically-using-multicore) and [here](https://stackoverflow.com/questions/12776497/what-does-jvm-do-to-use-multicore-cpu-resource) – vincrichaud Apr 25 '18 at 11:29
  • @Niza Siwale - can you explain what you think the difference is between parallel programming and multi-threading, because I don't understand your comment at all. – rghome Apr 25 '18 at 11:35
  • @rghome Multiple threading is simply doing work between threads while parallel programming is doing it between GPUs/CPUs. Multi threading usually happens on the same CPU – Niza Siwale Apr 25 '18 at 11:43
  • @Niza Siwale - the OP is talking about a multi-core CPU though. The threads can run in parallel across the cores. You don't need C++ for that. – rghome Apr 25 '18 at 12:16
  • It is possible that throughput is bottlenecked by harddrive performance. In fact, if the harddrive is a mechanical one, you might get disk thrashing which would in fact make things go slower, which is what you're seeing. Basically, with many readers and writes, the harddrive spends most of its time seeking. You could try writing to a "null" OutputStream and see how performance scales with threads. If you get good scaling, then I/O is probably your bottleneck. – volley Sep 06 '18 at 06:32
  • (Unrelated comment: I suspect the ObjectOutputStream should be flushed (flush()) or even closed (close()) before the CodedOutputStream is constructed. Otherwise data from CodedOutputStream may be interleaved with the key data.) – volley Sep 06 '18 at 06:36

1 Answers1

0

Here one has the case of processing an InputStream to an OutputStream. For that one could use java nio Piped I/O, done with two threads. This saves blocking on read and write.

The executor.shutdown(); after the for loop seems premature.

The rest is okay.

Maybe your question aims at exploiting the physical cores in the JVM. Last I knew, Linux is better bestowed than Windows on this point, but I might very well err.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138