我正在尝试比较 Java 8 和 PLINQ (C#/.Net 4.5.1) 中的并行流之间的性能。
这是我在我的机器上得到的结果(系统制造商 Dell Inc. 系统型号 Precision M4700 Processor Intel(R) Core(TM) i7-3740QM CPU @ 2.70GHz, 2701 Mhz, 4 Core(s), 8 Logical安装的处理器 物理内存 (RAM) 16.0 GB 操作系统名称 Microsoft Windows 7 Enterprise Version 6.1.7601 Service Pack 1 Build 7601)
C# .Net 4.5.1(X64 版本)
连续剧:
470.7784、491.4226、502.4643、481.7507、464.1156、463.0088、546.149、481.2942、502.414、483.1166
平均:490.6373
并行:
158.6935、133.4113、217.4304、182.3404、184.188、128.5767、160.352、277.2829、127.6818、213.6832
平均:180.5496
Java 8 (X64)
连续剧:
471.911822、333.843924、324.914299、325.215631、325.208402、324.872828、324.888046、325.53066、325.765791、325.935861
平均:326.241715
并行:
212.09323, 73.969783, 68.015431, 66.246628, 66.15912, 66.185373, 80.120837, 75.813539, 70.085948, 66.360769
平均:70.3286
看起来 PLINQ 不能跨 CPU 内核扩展。我想知道我是否遗漏了什么。
这是 C# 的代码:
class Program
{
static void Main(string[] args)
{
var NUMBER_OF_RUNS = 10;
var size = 10000000;
var vals = new double[size];
var rnd = new Random();
for (int i = 0; i < size; i++)
{
vals[i] = rnd.NextDouble();
}
var avg = 0.0;
Console.WriteLine("Serial:");
for (int i = 0; i < NUMBER_OF_RUNS; i++)
{
var watch = Stopwatch.StartNew();
var res = vals.Select(v => Math.Sin(v)).ToArray();
var elapsed = watch.Elapsed.TotalMilliseconds;
Console.Write(elapsed + ", ");
if (i > 0)
avg += elapsed;
}
Console.Write("\nAverage: " + (avg / (NUMBER_OF_RUNS - 1)));
avg = 0.0;
Console.WriteLine("\n\nParallel:");
for (int i = 0; i < NUMBER_OF_RUNS; i++)
{
var watch = Stopwatch.StartNew();
var res = vals.AsParallel().Select(v => Math.Sin(v)).ToArray();
var elapsed = watch.Elapsed.TotalMilliseconds;
Console.Write(elapsed + ", ");
if (i > 0)
avg += elapsed;
}
Console.Write("\nAverage: " + (avg / (NUMBER_OF_RUNS - 1)));
}
}
Java 代码如下:
import java.util.Arrays;
import java.util.Random;
import java.util.stream.DoubleStream;
public class Main {
private static final Random rand = new Random();
private static final int MIN = 1;
private static final int MAX = 140;
private static final int POPULATION_SIZE = 10_000_000;
public static final int NUMBER_OF_RUNS = 10;
public static void main(String[] args) throws InterruptedException {
Random rnd = new Random();
double[] vals1 = DoubleStream.generate(rnd::nextDouble).limit(POPULATION_SIZE).toArray();
double avg = 0.0;
System.out.println("Serial:");
for (int i = 0; i < NUMBER_OF_RUNS; i++)
{
long start = System.nanoTime();
double[] res = Arrays.stream(vals1).map(Math::sin).toArray();
double duration = (System.nanoTime() - start) / 1_000_000.0;
System.out.print(duration + ", " );
if (i > 0)
avg += duration;
}
System.out.println("\nAverage:" + (avg / (NUMBER_OF_RUNS - 1)));
avg = 0.0;
System.out.println("\n\nParallel:");
for (int i = 0; i < NUMBER_OF_RUNS; i++)
{
long start = System.nanoTime();
double[] res = Arrays.stream(vals1).parallel().map(Math::sin).toArray();
double duration = (System.nanoTime() - start) / 1_000_000.0;
System.out.print(duration + ", " );
if (i > 0)
avg += duration;
}
System.out.println("\nAverage:" + (avg / (NUMBER_OF_RUNS - 1)));
}
最佳答案
两个运行时都会决定使用多少线程来完成并行操作。这是一个非常重要的任务,可以考虑很多因素,包括任务受 CPU 限制的程度、完成任务的估计时间等。
每个运行时都是关于使用多少线程来解决请求的不同决定。就系统范围的调度而言,这两个决定显然是对还是错,但 Java 策略执行基准测试的效果更好(并且为系统上的其他任务留出更少的 CPU 资源)。
关于c# - PLINQ (C#/.Net 4.5.1) 与 Stream (JDK/Java 8) 性能对比,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23771022/