jeremyvillalobos
jeremyvillalobos

Reputation: 1815

Multi-core Android

I have run simple parallel algorithm drawing the mandelbrot set to test parallel computations on a Nexus 7 (Tegra 3, 4+1 cores). After running several times I get 1.5 seconds for serial and 1.0 for parallel, but parallel and serial come really close to each other at 1.3 seconds.

The square is 700x700 pixels, and the mandelbrot code I use is from

http://rosettacode.org/wiki/Mandelbrot_set#Java

The parallel implementation runs two halves of mandelbrot like this

    public void mandelbrotParallel() {
    Thread t1 = new Thread(new Runnable() {
        public void run() {
            mandelbrotOne();
        }
    });
    Thread t2 = new Thread(new Runnable() {
        public void run() {
            mandelbrotTwo();
        }
    });
    t1.start();
    t2.start();
    try {
        t1.join();
        t2.join();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    mHandler.post(new Runnable() {
        public void run() {
            v.setBmp(bmp);
            v.invalidate();
        }
    });
}

I have run a simple vector addition before and found similar anecdotal results (no scientific rigor). So I wonder if there is anything special one has to do to get Android to fire up multiple cores to get a task done.

Based on quick conversations with Google, it could be that the cores are dormant and wait for the computation to be truly long running (multiple seconds) before the cores are turned on... Is this true ? If so, are there API calls from Java (no JNI) that can be done to preemptively wake up the cores ?

Upvotes: 5

Views: 3573

Answers (2)

Klaas van Gend
Klaas van Gend

Reputation: 1128

A normal Android system tries to be conservative. So if you create a new thread and start some heavy computations, the Linux kernel will first run on one core and increase its core speed. Once the core has been 'busy' over a certain threshhold for a while, only then the kernel starts another core.

The same is true in the other direction: once the system calms down, it will slowly turn off cores and reduce frequency.

From a developer point of view, you cannot influence this on a 'normal' Android. Android has no API to wake up a certain amount of cores or set a certain core frequency.


If you can switch to a rooted Android, you have more options, as the regular Linux kernel does have options to influence the core frequencies and the number of active cores. This is done through 'governors'. A normal Linux kernel has quite a few options. For this question, you are interested in setting the performance governor, which will keep a core awake and at its highest frequency.

The Linux kernel interface is in the /sys file system. I'm going to show adb shell commands here and leave it to you to turn it into Java open, read and write commands.

cd /sys/devices/system/cpu

Within this directory, you'll find virtual files that indicate how many cores are present in the system:

cat possible

should give the answer 0-3 in your Tegra 3 case. The kernel doesn't know that if only one core is running, it secretly moves to the spare low-power core. There are also directories cpu0 cpu1 cpu2 cpu3. Depending on the kernel version, they may only appear if a core is activated. Each of the cpu directories contains a directory cpufreq where you can interact with the cpufreq subsystem. It should contain a file scaling_available_governors that shows which cpu governors are available. Only on a rooted system, you can do:

echo "performance" >cpu0/cpufreq/scaling_governor

To set the governor that will keep the core running at its highest frequency. On a non-rooted system, you'll get the error "permission denied".


To show the influence of this behavior, Vector Fabrics created a test application that performs an inpainting algorithm on OpenCV in parallel. The application measures both sequential and parallel performance up to 4 cores. Even when running the parallel version twice, the measurements vary due to starting up the cores. Have a look for yourself (download form the app store): http://www.vectorfabrics.com/products/case-study/opencv_inpaint

Upvotes: 2

Brett Duncavage
Brett Duncavage

Reputation: 2183

This sounds like a candidate for RenderScript. In a nutshell, it allows you to do computationally expensive operations that take advantage of all available acceleration resources (multiple cores, GPU compute, dsp, etc). From the docs:

Renderscript gives your apps the ability to run operations with automatic parallelization across all available processor cores. It also supports different types of processors such as the CPU, GPU or DSP. Renderscript is useful for apps that do image processing, mathematical modeling, or any operations that require lots of mathematical computation.

You'd have to rewrite your Mandelbrot code in C, but you won't have to break it apart into pieces since parallelization will be taken care of for you.

Using RenderScript from Android code is straightforward as described here.

Upvotes: 2

Related Questions