【问题标题】:Why using scala parallelism have slower performance in this case?为什么在这种情况下使用 scala 并行性会降低性能?
【发布时间】:2013-02-23 19:31:20
【问题描述】:

TestClassString 类返回一个 java.util.List of Strings

对象TestViewPerformance记录调用TestViewController.iterateList方法的时间。

在 iterateList 中,运行这个小程序所花费的时间在删除并行性后始终至少快 100 毫秒:

mySeq.par 至 我的序列

我意识到这里有用于测量 scala 性能的基准测试工具: http://docs.scala-lang.org/overviews/parallel-collections/performance.html

但我仍然希望这个程序使用基于当前毫秒时间的并行性运行得更快吗? .par 循环中的所有代码是否都分布在多个内核上?

这是完整的代码:

package testpackage

import java.util.Calendar

object TestViewPerformance {

  def main(args:Array[String]) = {

      val before = Calendar.getInstance().getTimeInMillis()

      val testViewController = new TestViewController();
      val testClassString : TestClassString = new TestClassString()

      val folderList = testClassString.getStringList()
      var buffer = new scala.collection.mutable.ListBuffer[String]
      val seq = scala.collection.JavaConversions.asScalaBuffer(folderList);

      /*
       * this method (iterateList) is where the parallelism occurs
       */
      testViewController.iterateList(seq)

      val after = Calendar.getInstance().getTimeInMillis()

      println(before)
      println(after)
      println(after-before)

  }

  class TestViewController {

      def iterateList(mySeq : Seq[String]) = {

        for (seqVal<- mySeq) {
            if(seqVal.equalsIgnoreCase("test")){            

            }
        }   
}

}

}

package testpackage;

import java.util.ArrayList;
import java.util.List;

public class TestClassString {

    public List<String> getStringList(){

        List<String> l = new ArrayList<String>();

        for(int i = 0; i < 1000000; ++i){
            String test = ""+Math.random();
            l.add(test);
        } 

        return l;
    }

}

【问题讨论】:

    标签: java scala


    【解决方案1】:

    因为您的基准测试是测量线程切换和量子波动的开销。至少将 Thread.sleep(1) 添加到您的循环中,看看会发生什么:

    scala> val strings = (1 to 10000).map(_ + Math.random().toString)
    strings: scala.collection.immutable.IndexedSeq[String] = Vector(10.8907863042670979, 20.2871957696184603, 30.20011325237932742, 40.7490949002788928, 50.5073228980632211...
    scala> val time = System.currentTimeMillis; 
           | for (str <- strings.par) {Thread.sleep(1)}; 
           | System.currentTimeMillis - time
    res0: Long = 1398
    
    scala> val time = System.currentTimeMillis; 
           | for (str <- strings) {Thread.sleep(1)}; 
           | System.currentTimeMillis - time
    res3: Long = 11129
    

    【讨论】:

    • 添加 Thread.sleep(1) 确实使它运行得更快。我很困惑为什么。在生产中不会使用'Thread.sleep',这是否意味着我不应该使用.par,因为没有它似乎运行得更快?
    • @user470184:在生产中你会有一些处理,可能需要超过一毫秒。您必须了解并行集合会产生一些开销来将任务拆分为线程,以管理它们等等。因此,如果您在循环中执行的任何处理都小于此开销,则不值得使用 par。
    【解决方案2】:

    这可能是因为每次迭代中的大部分时间都用于打印到System.out,这是一个同步操作,因此无法并行化。因此,启动线程、调度线程和同步线程所带来的成本使得并行迭代比顺序迭代慢。

    【讨论】:

    • ive 删除了 println 但结果相同,“if 条件”永远不会为真。
    • 让每次迭代都做一些实质性的事情(或休眠一段时间)。比较两个长度或第一个字符总是不同的字符串是如此之快,以至于在 1,000,000 个实例上并行化它不会带来任何性能提升。
    猜你喜欢
    • 2017-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多