这个系列包括算法导论学习过程的记录。

最初学习归并算法,对不会使其具体跑在不同的核上报有深深地怨念,刚好算倒重温了这个算法,闲来无事,利用java的thread来体验一下并行归并算法。理论上开的thread会被分配在不同的核上(核没用完的情况下)。当然利用c++来实现更好,这里主要体验一下思路。

=========================================================

  • 基本Merge Sort

    Merge Sort的具体思路不再详诉,将其包装为MergeSort类.
public class MergeSort {

    public static void sort(int[] numbers){
sort(numbers,0,numbers.length);
} public static void sort(int[] numbers,int pos,int end){
if ((end - pos) > 1) {
int offset = (end + pos) / 2;
sort(numbers, pos, offset);
sort(numbers, offset, end);
merge(numbers, pos, offset, end);
}
} public static void merge(int[] numbers,int pos,int offset,int end){
int[] array1 = new int[offset - pos];
int[] array2 = new int[end - offset];
System.arraycopy(numbers, pos, array1, 0, array1.length);
System.arraycopy(numbers, offset, array2, 0, array2.length);
for (int i = pos,j=0,k=0; i < end ; i++) {
if (j == array1.length) {
System.arraycopy(array2, k, numbers, i, array2.length - k);
break;
}
if (k == array2.length) {
System.arraycopy(array1, j, numbers, i, array1.length - j);
break;
}
if (array1[j] <= array2[k]) {
numbers[i] = array1[j++];
} else {
numbers[i] = array2[k++];
}
}
} }
  • 并行Merge Sort

    并行实现Merge Sort的大体思路为将原来递归拆分其中的一部分换成新开的线程来接管,也就是拆分成一些子串,给不同的核心来处理。

    以我的电脑(RMBP Late2013 i5 4258u)为例,其有4个可用核。 递归拆分2次,也就是拆分成4个子串。然后分别在四个核上利用Merge sort对这些子串进行排序。完成后利用同步工具CountDownLatch来提示完成任务,父进程Merge两个已经排好的子串。



    示意图如下:







    将其包装为MergeParallelSort类如下:

import java.util.Random;
import java.util.concurrent.CountDownLatch; public class MergeParallelSort { // 最大可并行深度,为log处理器数
private static final int maxParallelDepth = (int) (Math.log(Runtime.getRuntime().availableProcessors())
/ Math.log(2)); public static void sort(int[] numbers) {
sort(numbers, 0, numbers.length, maxParallelDepth);
} public static void sort(int[] numbers , int parallelDepth) {
sort(numbers, 0, numbers.length, parallelDepth);
} public static void sort(int[] numbers, int start, int end) {
sort(numbers, start, end, maxParallelDepth);
} public static void sort(int[] numbers, int start, int end, int parallelDepth) {
sortParallel(numbers, start, end, parallelDepth > maxParallelDepth ? maxParallelDepth : parallelDepth, 1);
} /**
* Do Merge Sort in parallel way
*
* @param numbers
* @param start
* @param end
* @param parallelDepth 当前并行深度
* @param depth 当前拆分深度
*/
public static void sortParallel(final int[] numbers, final int start, final int end, final int parallelDepth,
final int depth) {
if ((end - start) > 1) {
//同步工具,等待其两个子线程完成任务后归并
final CountDownLatch mergeSignal = new CountDownLatch(2);
final int offset = (end + start) / 2;
new SortThread(depth, parallelDepth, numbers, mergeSignal, start, offset).start();
new SortThread(depth, parallelDepth, numbers, mergeSignal, offset, end).start(); //等待两个子线程完成其工作
try {
mergeSignal.await();
} catch (InterruptedException e) {
e.printStackTrace();
} MergeSort.merge(numbers, start, offset, end);
}
} static class SortThread extends Thread { private int depth;
private int parallelDepth;
private int[] numbers;
private CountDownLatch mergeSignal;
private int start;
private int end; /**
* @param depth
* @param parallelDepth
* @param numbers
* @param mergeSignal
* @param start
* @param end
*/
public SortThread(int depth, int parallelDepth, int[] numbers, CountDownLatch mergeSignal, int start, int end) {
super();
this.depth = depth;
this.parallelDepth = parallelDepth;
this.numbers = numbers;
this.mergeSignal = mergeSignal;
this.start = start;
this.end = end;
} @Override
public void run() {
if (depth < parallelDepth) {
sortParallel(numbers, start, end, parallelDepth, (depth + 1));
} else {
MergeSort.sort(numbers, start, end);
}
mergeSignal.countDown();
} } public static void main(String[] args) {
System.out.println("Parallel Merge Sort test");
System.out.println("Processor number:" + Runtime.getRuntime().availableProcessors());
System.out.println("Array Size:10000000");
long time_start, time_end;
long time_para, time_single;
int array[] = new int[10000000];
int array1[] = new int[10000000];
int array2[] = new int[10000000];
Random random = new Random(); for (int i = 0; i < 1000; i++) {
array[i] = random.nextInt(1000000);
} System.arraycopy(array, 0, array1, 0, array1.length);
System.arraycopy(array, 0, array2, 0, array2.length); // parallelSort
time_start = System.currentTimeMillis();
MergeParallelSort.sort(array1);
time_end = System.currentTimeMillis();
time_para = time_end - time_start; // orginalSort
time_start = System.currentTimeMillis();
MergeSort.sort(array2);
time_end = System.currentTimeMillis();
time_single = time_end - time_start; System.out.println("time_para:" + time_para);
System.out.println("time_single:" + time_single);
System.out.println("Speed up:"+(float)time_single/time_para);
}
}
  • 输出示例&总结



    尝试过数组大小的几组例子,当输入规模过小(size小于100000),并行化效率会低于直接单核处理,可能是开Thread以及等待其他Thread完成导致。当输入规模大起来,加速比也并非理想的4倍。本身基于JVM写并行化并没有明确地将线程分配到具体的核心,待以后有机会研究,此次只是当作并行化初体验罢。

算法学习:并行化初体验_JAVA实现并行化归并算法的更多相关文章

  1. 冒泡,快排算法之javascript初体验

    引子:javascript实际使用的排序算法在标准中没有定义,可能是冒泡或快排.不用数组原生的 sort() 方法来实现冒泡和快排. Part 1:冒泡排序(Bubble Sort) 原理:临近的两数 ...

  2. kafka 学习之初体验

    学习问题: 1.kafka是否需要zookeeper?2.kafka是什么?3.kafka包含哪些概念?4.如何模拟客户端发送.接受消息初步测试?(kafka安装步骤)5.kafka cluster怎 ...

  3. Docker学习<一>--初体验Windows环境下安装

    背景 今天想试用spring boot与jwt协议的实现,配套就需要使用redis,但redis似乎windows环境版本部署起来不是那么舒心,果断尝试使用docker. 下载 下载地址: 稳定版:h ...

  4. UITextView(文本视图) 学习之初体验

    UITextView文本视图相比与UITextField直观的区别就是UITextView可以输入多行文字并且可以滚动显示浏览全文.常见UITextView使用在APP的软件简介.内容详情显示.小说阅 ...

  5. Javascript经典算法学习1:产生随机数组的辅助类

    辅助类 在几个经典排序算法学习部分,为方便统一测试不同算法,新建了一个辅助类,主要功能为:产生指定长度的随机数组,提供打印输出数组,交换两个元素等功能,代码如下: function ArraySort ...

  6. 有感FOC算法学习与实现总结

    文章目录 基于STM32的有感FOC算法学习与实现总结 1 前言 2 FOC算法架构 3 坐标变换 3.1 Clark变换 3.2 Park变换 3.3 Park反变换 4 SVPWM 5 反馈部分 ...

  7. 数据结构(逻辑结构,物理结构,特点) C#多线程编程的同步也线程安全 C#多线程编程笔记 String 与 StringBuilder (StringBuffer) 数据结构与算法-初体验(极客专栏)

    数据结构(逻辑结构,物理结构,特点) 一.数据的逻辑结构:指反映数据元素之间的逻辑关系的数据结构,其中的逻辑关系是指数据元素之间的前后件关系,而与他们在计算机中的存储位置无关.逻辑结构包括: 集合 数 ...

  8. (数据科学学习手札35)tensorflow初体验

    一.简介 TensorFlow时谷歌于2015年11月宣布在Github上开源的第二代分布式机器学习系统,目前仍处于快速开发迭代中,有大量的新功能新特性在陆续研发中: TensorFlow既是一个实现 ...

  9. 深度学习之TensorFlow安装与初体验

    深度学习之TensorFlow安装与初体验 学习前 搞懂一些关系和概念 首先,搞清楚一个关系:深度学习的前身是人工神经网络,深度学习只是人工智能的一种,深层次的神经网络结构就是深度学习的模型,浅层次的 ...

随机推荐

  1. ASP.NET Core 源码学习之 Logging[3]:Logger

    上一章,我们介绍了日志的配置,在熟悉了配置之后,自然是要了解一下在应用程序中如何使用,而本章则从最基本的使用开始,逐步去了解去源码. LoggerFactory 我们可以在构造函数中注入 ILogge ...

  2. javascript 用Activex方法调用数据库中的数据,只可用于IE

    // JavaScript source code //创建数据库连接对象 var conn = new ActiveXObject("ADODB.Connection"); // ...

  3. Hello world! My first blog!

    Hello world! My first blog!

  4. JS正则密码复杂度校验之:JS正则匹配半角英文符号

    概述 在JS密码校验中常常会遇到密码强度的校验需求,借用一位朋友提问的图,他在工作中遇到的一个比较经典的密码强度校验要求: 这个需求有两个难点,一,是如何使用正则匹配所有半角英文标点符号,二,是如何验 ...

  5. SpringMVC详解(一)------入门实例

    本系列教程我们将详细的对SpringMVC进行介绍,相信你在学完本系列教程后,一定能在实际开发中运用自如. 1.什么是 SpringMVC ? 在介绍什么是 SpringMVC 之前,我们先看看 Sp ...

  6. android学习笔记WebView的基本使用

    WebView可以看做是一个浏览器,它使用了WebKit渲染引擎加载显示网页. WebView的使用需要掌握下面几点, 1,首先需要开启应用网络访问权限 在AndroidMinafest.xml中添加 ...

  7. Spring集成RabbitMQ-使用RabbitMQ更方便

    如果提到Spring,你脑海中对他的印象还停留在SSH三大框架之一,那或许你该好好重新认识这个家伙. 在IT技术日新月异的今天,他还能让你忘不了并与他朝夕相处,他,肯定有自己的绝活.如今他早已经不是孤 ...

  8. redux深入理解之中间件(middleware)

    理解reduce函数 reduce() 方法接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始缩减,最终为一个值. arr.reduce([callback, initi ...

  9. Orleans简单配置

    Orleans简单配置 这是Orleans系列文章中的一篇.首篇文章在此 话说曾几何时,我第一次看到xml文件,心中闪过一念想:"这<>是什么鬼?"-用ini或者jso ...

  10. 谷歌。百度,阿里云,机器翻译简单PK。

    原文:Google 的免费翻译服务可提供简体中文和另外 100 多种语言之间的互译功能,可让您即时翻译字词.短语和网页内容. 阿里云:google's free translation service ...