我并行化了一个Java程序。在具有4个内核的Mac上,下面是不同线程数的时间。
threads # 1 2 4 8 16
time 2597192200 1915988600 2086557400 2043377000 1931178200
在具有两个插槽的Linux服务器上,每个插槽有4个核心,下面是测量时间。
threads # 1 2 4 8 16
time 4204436859 2760602109 1850708620 2370905549 2422668438
如您所见,加速远离线性加速。在这种情况下几乎没有并行化开销,如同步或I / O依赖性。
我有两个问题:
答案 0 :(得分:1)
嗯,他们暗示算法不受CPU限制。它可能受到其他东西的约束 - 它可能是内存,I / O或其他东西,但它可能不受CPU限制。
答案 1 :(得分:1)
Amdahl's Law解释说,并行化程序所获得的加速取决于程序可并行化的程度。
我们还必须增加协调并行性的开销。
因此,我们考虑程序的百分比/部分可并行化,以及产生的开销(同步,通信,错误共享等)。
您可以同时从2个不同的硬盘驱动器中读取而不会减速。
但是,通常并行性并不能提高读取硬盘的速度。
硬盘驱动器(即带有旋转磁盘的驱动器)已经过优化,可以按顺序读取,在存储器位置之间跳转会降低整体内存传输速度。
固态硬盘实际上非常擅长随机访问数据,在内存中跳转,因此使用固态硬盘保持读/写队列是一个好主意。
了解缓存行的想法有助于避免错误共享。
这种类型的内存操作可以有效地并行化,例如通过将数组划分为四个分区来迭代数组。
我假设您的时间是纳秒级,因此在计算机1上,程序耗时2.5秒,然后平稳约2秒,峰值为1.9秒。
我希望您同时运行最少的后台程序,并且您执行了几次这些测试以消除不规则性。
此外,由于Java虚拟机的即时编译(JIT),时序可能会出现异常,因此为了准确计算时间,您希望在循环中运行代码几次,并存储时间最后一次迭代。 (或预编译为本机代码)。
此外,自从第一次运行程序以来,从硬盘驱动器中使用的大部分数据都将被移动到缓存中,因此以后的执行应该更快。 (因此要么在循环之后使用上次运行的时间来确保内存在缓存中,要么使用第一个时序但是关闭电源并在计算机之间进行计时)。
仅根据您的时间安排,这很难说。
第一台电脑用了2.5秒,然后用2个线程加速了20%,但之后停留了大约2.0秒。
本身,这种加速可能只是JIT的结果,高速缓冲存储器由1个线程上的时序填充。在那之后,运行时间的任何差异可能只是噪音。
第二台计算机用了4.2秒,然后是2.8秒,然后是1.9秒,然后回到了大约2.3秒。
这个似乎确实展示了某种类型的并行加速,但是一些争用时间(内存,缓存行,同步等)如4个线程到8的时间增加所证明的那样线程。
在代码上使用分析器,确定代码的哪些部分占用的时间最多。
(您可以通过调试代码并打破并查看程序的位置来模拟分析器。重复10次,以查看是否有一个部件比另一部件按比例停止。)
使用更好的算法或以更好的方式排列内存中的数据(数据结构)。
在问题中利用更多的并行性。
尝试使硬盘驱动器内存顺序读取。也许只有一个线程具有来自硬盘驱动器的读取,然后将数据放入并发队列中以供其他线程操作。