- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在研究 Java 8 中引入的并行排序概念。根据 doc .
If the length of the specified array is less than the minimum granularity, then it is sorted using the appropriate Arrays.sort method.
然而,规范并未指定此最低限制。
当我在 java.util.Arrays
中查找代码时,它被定义为
private static final int MIN_ARRAY_SORT_GRAN = 1 << 13;
即数组中的 8192 个值
根据提供的解释 here .我理解为什么该值被硬编码为 8192。
It was designed keeping the current CPU architecture in mind.
With the-XX:+UseCompressedOops
option being enabled by default, any system with less than 32GB RAM would be using 32bit(4bytes) pointers. Now, with a L1 Cache size of 32KB for data portion, we can pass 32KB/4Bytes = 8KB of data at once to CPU for computation. That's equivalent to 8192 bytes of data being processed at once.
因此对于一个正在对字节数组进行排序的函数 parallelSort(byte[])
这是有道理的。您可以将最小并行排序限制保持为 8192 个值(对于字节数组,每个值 = 1 个字节)。
但是如果你考虑public static void parallelSort(int[] a)
一个整型变量是 4 字节(32 位)。所以理想情况下,在 8192 字节中,我们可以一次在 CPU 缓存中存储 8192/4 = 2048 个数字。因此本例中的最小粒度假设为 2048。
为什么 Java 中的所有 parallelSort 函数(例如 byte[]、int[]、long[] 等)都使用 8192 作为默认最小值。执行并行排序需要多少个值?
它不应该根据传递给 parallelSort 函数的类型而变化吗?
最佳答案
首先,您似乎误读了链接的解释。 L1 数据缓存为 32Kb,因此对于 int[]
它非常适合:32768/4=8192
int 可以放入 L1 缓存中。
其次,我认为给出的解释不正确。它专注于指针,所以它主要说的是对象数组的排序,但是当你比较对象数组中的数据时,你总是需要解引用这些指针来访问真正的数据。如果您的对象具有非原始字段,您将不得不进一步取消引用它们。例如,如果您对字符串数组进行排序,您不仅要访问数组本身,还要访问 String
对象和存储在其中的 char[]
数组。所有这些都需要许多额外的缓存行。
我在 review thread 中没有找到关于这个特定值的任何明确解释对于这个改变。以前是 256,然后作为 JDK-8014076 的一部分更改为 8192更新。我认为它只是在一些合理的测试套件上显示出最佳性能。为不同的情况保持单独的阈值会增加更多的复杂性。可能测试表明它没有返回。请注意,对于 Object[]
数组来说,理想的阈值是不可能的,因为比较函数是用户指定的,并且可能具有任意复杂性。对于足够复杂的比较函数,并行化甚至非常小的数组可能是合理的。
关于java - 为什么在 Java8 中将最小粒度定义为 8192 以便从并行排序切换到 Arrays.sort 而不管数据类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36128533/
我有 2 个事实表,每个表都有一个度量组,生产和生产订单。生产具有较低粒度的生产信息(在组件级别)生产订单具有较高级别的信息(具有抬头数量等的订单级别)。 我在 productionorderid 的
关闭。这个问题是off-topic .它目前不接受答案。 想改善这个问题吗? Update the question所以它是 on-topic对于堆栈溢出。 9年前关闭。 Improve this q
我第一次尝试了解 Akka/Actors,并且对每个 Actor 职责的粒度有点困惑。 在我的应用程序中,有可以使用 WidgetRegistrar 注册/取消注册的 Widget。要向 Regist
我们一直在使用 MVP 模式和 Winforms,并取得了相当大的成功。然而,关于 MVP 总是弹出一个问题: 对于演示者来说,什么是好的粒度? 我的意思是:对于 Winforms,细粒度通常适用于用
我通常使用 git add -p 添加更改,而且很多时候有几个代码块的大块头,由空行分隔。 但是,git 不会进一步拆分 大块头,我不得不求助于手动编辑。 如何增加 hunk 的粒度,以便每个代码块都
例如,我看到 dumps.wikimedia.org/other/pagecounts-raw/,但那里没有特定国家/地区的数据... 最佳答案 据我所知,没有。出于明显的隐私原因,发布的页面查看统计
JavaScript 的源映射似乎通常不比 token 粒度更精细。 例如,identity-map uses token granularity . 我知道我看过其他例子,但不记得在哪里。 为什么我
我有这些目录: ./Tools ./ook/Tools. 我在 setup.cfg 中的 py.test 的 norecursedirs 选项中添加了 Tools。正如预期的那样,当 py.test
我正在使用这个 Accelerometer graph来自 Apple 并尝试转换他们的 G-force 代码以计算 +/- 128。 下图显示标签中的 x、y、z 值与图表上的输出不匹配:(请注意,
此问题围绕 Android 应用程序的架构展开。 在使用 LifeCycle 组件 ViewModel 时,最好是每个 fragment 一个 ViewModel 还是订阅 fragment 的父 A
我是一名优秀的程序员,十分优秀!