简体   繁体   English

Scala quickSort使用Ordering [T]速度慢10倍

[英]Scala quickSort 10x slower when using Ordering[T]

I was doing some sorting of integer indices based on a custom Ordering. 我正在根据自定义排序对整数索引进行一些排序。 I found that the Ordering[T] used here makes the sort at least 10 times slower than handcrafted quickSort using direct calls to the compare method. 我发现这里使用的Ordering [T]使用直接调用compare方法比使用手工制作的quickSort慢至少10倍。 That seems outrageously costly! 这看起来非常昂贵!

val indices: Array[Int] = ...

class OrderingByScore extends Ordering[Int] { ... }

time { (0 to 10000).par.foreach(x => {
  scala.util.Sorting.quickSort[Int](indices.take(nb))(new OrderingByScore)
})}
// Elapsed: 30 seconds

Compared to the hand crafted sortArray found here but modified to add an ord: Ordering[Int] parameter: 与手工制作的sortArray相比, 此处可以修改以添加ord: Ordering[Int]参数:

def sortArray1(array: Array[Int], left: Int, right: Int, ord: Ordering[Int]) = ...

time { (0 to 10000).par.foreach(x => {
  sortArray1(indices.take(nb), 0, nb - 1, new OrderingByScore)
})}
// Elapsed: 19 seconds

And finally, same piece of code but using exact type instead ( ord: OrderingByScore ): 最后,使用相同的代码但使用精确类型( ord: OrderingByScore ):

def sortArray2(array: Array[Int], left: Int, right: Int, ord: OrderingByScore) = ...

time { (0 to 10000).par.foreach(x => {
  sortArray2(indices.take(nb), 0, nb - 1, new OrderingByScore)
})}
// Elapsed: 1.85 seconds

I'm quite surprised to see such a difference between each versions! 我很惊讶地发现每个版本之间存在这样的差异!

In my example, indices array is sorted based on the values found in another Doubles array containing a combined scores. 在我的示例中,indices数组基于在包含组合分数的另一个Doubles数组中找到的值进行排序。 Also, the sorting is stable as it use the indices itself as a secondary comparison. 此外,排序是稳定的,因为它使用索引本身作为次要比较。 On a side note, to make testing reliable, I had to "indices.take(nb)" within the parallel loop since sorting modifies input array. 另外,为了使测试可靠,我必须在并行循环中使用“indices.take(nb)”,因为排序会修改输入数组。 This penalty in negligible compared to the problem that brings me here. 与我带来的问题相比,这种惩罚可以忽略不计。 Full code on gist here . 对要点的完整代码在这里

Your suggestions are much welcomed to improve on.. But try not to change the basic structure of an indices and scores arrays. 你的建议很受欢迎改进..但尽量不要改变索引和分数数组的基本结构。

Note: I'm running within scala 2.10 REPL. 注意:我在scala 2.10 REPL中运行。

The problem is that scala.math.Ordering is not specialized. 问题是scala.math.Ordering不是专门的。 So every time you call the compare method with a primitive like Int , both arguments of type Int are being boxed to java.lang.Integer . 所以每次调用的是具有基本类似的比较方法的时间Int ,类型的两个参数Int被装箱为java.lang.Integer That is producing a lot of short-lived objects, which slows things down considerably. 这会产生许多短暂的物体,这会大大减慢速度。

The spire library has a specialized version of Ordering called spire.algebra.Order that should be much faster. 尖顶库有一个专门版本的Ordering,名为spire.algebra.Order ,速度要快得多。 You could just try to substitute it in your code and run your benchmark again. 您可以尝试在代码中替换它并再次运行基准测试。

There are also sorting algorithms in spire. 尖顶中还有排序算法 So maybe just try those. 所以也许只是试试那些。

Basically, whenever you want to do math with primitives in a high performance way, spire is the way to go. 基本上,无论何时你想以高性能的方式用基元进行数学运算,尖顶都是可行的方法。

Also, please use a proper microbenchmarking tool like Thyme or JMH for benchmarks if you want to trust the results. 此外,如果您想要信任结果,请使用适当的微基准测试工具(如ThymeJMH)进行基准测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 慢速SQL查询:在两个不同的联接中使用同一张表会使查询变慢10倍! - Slow SQL query: using the same table in two different joins causes query to become 10x slower! numpy float:比算术运算中的内置慢10倍? - numpy float: 10x slower than builtin in arithmetic operations? 为什么 DbContext.SaveChanges 在调试模式下慢 10 倍 - Why is DbContext.SaveChanges 10x slower in debug mode Laravel 4.1比4.0慢10倍 - Laravel 4.1 is 10x slower than 4.0 一台服务器上的MySQL比另一台服务器慢10倍 - MySQL 10x slower on one server compared to another 添加 JOIN 后 MySQL Group BY 慢 10 倍 - MySQL Group BY 10x slower after adding a JOIN Python websockets 以一种方式快速,但响应速度慢 10 倍 - Python websockets fast one way but 10x slower with response 使用较新版本的System.Data.SQLite / sqlite3.dll,在SQLite数据库上使用子查询进行查询的速度大约慢10倍 - Querying using subqueries on a SQLite database approx 10x slower using newer versions of System.Data.SQLite/sqlite3.dll 相对于x86,在x64下启动Winforms程序10倍 - Startup of Winforms program 10x slower under x64 relative to x86 为什么Spring MVC json序列化比手动调用jackson慢10倍? - Why is Spring MVC json serialization 10x slower than calling jackson manually?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM