如何在java中进行多处理,以及期望的速度增益?

时间:2011-11-03 21:16:45

标签: java multiprocessing

我是一个使用Java在csv文件上进行数据处理的新手。为此,我使用Java(线程池)的多线程功能将csv文件批量导入Java,并在每个行上执行一些操作。在我的四核上,多线程可以大大加快这个过程。

我很想知道多处理如何/更快地加速操作?如果有的话,是否有可以在某处获得的教程?(Java Basic Tutorial提到了一个类,但是我不熟悉语法来自己理解这个类:

来自http://download.oracle.com/javase/tutorial/essential/concurrency/procthread.html

  

Java虚拟机的大多数实现都是单个运行的   处理。 Java应用程序可以使用a创建其他进程   ProcessBuilder对象。多进程应用程序超出了范围   本课程 [他们在哪里解释?]

6 个答案:

答案 0 :(得分:4)

  

我很想知道多处理如何以及是否会进一步加快操作速度?

不,实际上它可能会使情况变得更糟。如果您要从多线程切换到多处理,那么您将多次有效地启动JVM。启动JVM并非易事。实际上,桌面计算机上的JVM启动方式与企业公司启动JVM的方式不同,只是为了减少小程序为典型最终用户启动的等待时间。

答案 1 :(得分:1)

检查JVM上的文档,看它是否支持多线程。太确定太阳了。 Java Concurrency In Practice是多线程的起点。

问题的第一部分是:从性能角度来看,多线程是否优于多线程?在具有强大多线程支持的系统中,从性能角度来看,线程应始终优于进程。线程之间存在更多隔离(没有共享内存,除非通过IPC机制明确设置),因此您可能希望采用多进程路由来防止危险线程相互踩踏。

对于数据处理,线程应该是最好的方法。如果本地计算机上的线程不够,我会跳过多进程解决方案,直接进入像Hadoop这样的map-reduce系统。

至于为什么多处理应用程序提到,我认为作者希望完整。虽然没有提供教程,但是附加文档的链接是。使用多处理的最大缺点是您必须处理进程间通信。与线程不同,你不能只是共享一些内存并在它周围抛出一些互斥量并称之为一天。


从评论中可以看出,“多处理”实际上存在一些混淆。线程是必须由代码创建的构造。有用于创建和管理线程的API。但是,可以在命令行上手动创建进程。在unix框中,执行以下操作以运行foo的四个实例(进程)。请注意,最终&是必需的。

$ ./foo & ./foo & ./foo & ./foo &

现在,如果您有一个foo需要处理的输入文件bar,请使用类似split的内容将其分成四个相等的段,并在其上运行foo:< / p>

$ ./foo bar.0 > bar.0.out & ./foo bar.1 > bar.1.out & ./foo bar.2 > bar.2.out & ./foo bar.3 > bar.3.out &

最后,您需要合并bar.?.out个文件。运行这样的测试应该会让您对使用重量级进程是否适合您的应用程序有所了解。如果您已经构建了一个多线程应用程序,那可能就好了。但随意进行一些实验,看看过程是否更好。一旦确定流程是可行的,请重新组织代码以使用ProcessBuilder自行启动流程。

答案 2 :(得分:1)

每个开发人员都应该对Amdahl定律有所了解,以了解多处理如何根据给定条件加速。

Amdahl定律是算法的并行化实现相对于串行算法的预期加速之间关系的模型,假设在并行化时问题大小保持不变。

这是一个很好的解读:阿姆达尔定律

Amdahl's law

答案 3 :(得分:1)

增益取决于映射/缩小数据所需的时间。

例如,如果文件在多台机器上加载(开始时就像分片文件系统那样),那么获取数据就没有延迟了。如果数据来自单个位置,则受到该机制的限制。

然后必须合并/汇总数据 - 不知道更多,无法猜测。如果所有处理都依赖于拥有所有数据,那么与最终结果可以独立计算相比,它的命中率更高。

你有非常少量的非常小的文件:除非你所做的事情在计算上很昂贵,否则我怀疑它是否值得付出努力,但很难说。假设没有网络/磁盘瓶颈,您将获得(非常)大致线性加速,并使用delta来聚合结果。真正的加速/增量取决于我们目前还不太了解的一系列因素。

OTOH,您可以设置一个小型Hadoop设置,然后尝试一下,看看会发生什么。

答案 4 :(得分:1)

有几种方法可以在Java中启动新进程:

  1. ProcessBuilder.start()
  2. Runtime.exec()适用于ProcessBuilder
  3. Apache Commons Exec适用于Runtime.exec()
  4. 使用ProcessBuilder

    ProcessBuilder pb =
    new ProcessBuilder("myCommand", "myArg1", "myArg2");
    Map<String, String> env = pb.environment();
    env.put("VAR1", "myValue");
    env.remove("OTHERVAR");
    env.put("VAR2", env.get("VAR1") + "suffix");
    pb.directory(new File("myDir"));
    File log = new File("log");
    pb.redirectErrorStream(true);
    pb.redirectOutput(Redirect.appendTo(log));
    Process p = pb.start();
    assert pb.redirectInput() == Redirect.PIPE;
    assert pb.redirectOutput().file() == log;
    assert p.getInputStream().read() == -1;
    

    使用Runtime

    Runtime r = Runtime.getRuntime();
    Process p = r.exec("firefox");
    p.waitFor(10, TimeUnit.SECONDS);
    p.destroy();
    

    使用Apache Commons Exec:

    String line = "AcroRd32.exe /p /h " + file.getAbsolutePath();
    CommandLine cmdLine = CommandLine.parse(line);
    DefaultExecutor executor = new DefaultExecutor();
    int exitValue = executor.execute(cmdLine);
    

    来自this的多处理和多线程之间的主要区别:

    • 多处理和多线程之间的主要区别在于多处理允许系统将两个以上的CPU添加到系统中,而多线程允许一个进程生成多个线程以提高系统的计算速度。
    • 多处理系统同时执行多个进程,而多线程系统允许同时执行进程的多个线程。
    • 创建进程会消耗时间甚至耗尽系统资源。但是,创建线程是经济的,因为属于同一进程的线程共享该进程的所有权。
    • 多处理可分为对称多处理和非对称多处理,而多线程则不进一步分类。

    其他链接:

答案 5 :(得分:0)

对于许多用例,在比较产生线程与产生进程以及比较线程之间的通信与进程间通信时,多线程比多处理具有更少的开销。

但是,在某些情况下,多线程会降低性能,使单个线程的性能超过多个线程,例如受false sharing严重影响的情况。使用多处理,由于每个进程都有自己的内存空间,因此不会发生错误共享,多处理解决方案可以胜过多线程解决方案。

总的来说,在选择并发编程解决方案时应该进行一些分析,因为性能最佳的解决方案可能会因具体情况而异。不能假设多线程优于多处理,因为存在多线程执行比单线程更差的反直觉情况。当性能是一个主要考虑因素时,运行基准来比较单线程单进程与多线程与多处理解决方案,以确保您真正获得预期的性能优势。

快速说明,在选择解决方案时,还有其他考虑因素。