我正在做一个简单的基准测试,在几个 Linux 机器上测试 Mono 的 ParallelFX 和 Java。.NET 的测试在 Windows 和 Linux 上运行良好,但我在 Java 版本上遇到了一些问题......
我可以看到指定数量的线程正在启动,但它们以一种奇怪的方式运行。就像他们开始了,但他们完成得很慢。他们继续开始,但需要永远完成。看起来它应该超过线程池的限制,而且我的 CPU 使用率在我看来就像它只使用一个或两个内核(我有一个 i7 处理器,所以应该尝试使用 8 之类的东西)。
是的,我知道我的整数和其他可能的东西也不是“线程安全的”。我现在真的不在乎。这里有更大的问题。
C#版本
public class Program
{
static void Main(string[] args)
{
const int numberOfCycles = 1000;
const int numbersPerCycle = 1000000;
Stopwatch swG = Stopwatch.StartNew();
int threadCount = 0;
int completeCount = 0;
Parallel.For(0, numberOfCycles, x =>
{
Console.WriteLine(string.Format("Starting cycle {0}. Thread count at {1}", x, threadCount++));
Random r = new Random();
Stopwatch sw = Stopwatch.StartNew();
List<double> numbers = new List<double>();
for (int i = 0; i < numbersPerCycle; i++)
{
numbers.Add(r.NextDouble() * 1000);
}
numbers.Sort();
double min = numbers.Min();
double max = numbers.Max();
completeCount++;
Console.WriteLine(string.Format("{0} cycles complete: {1:#,##0.0} ms. Min: {2:0.###} Max: {3:0.###}", completeCount, sw.ElapsedMilliseconds, min, max));
threadCount--;
});
Console.WriteLine(string.Format("All {0} cycles complete. Took {1:#,##0.0} ms.", numberOfCycles, swG.ElapsedMilliseconds));
Console.WriteLine("Press any key to continue.");
Console.ReadKey();
}
}
Java版
PS我很懒,从这里偷了秒表类:Java中有秒表吗?
public class JavaMonoTest {
static int threadCount = 0;
static int completeCount = 0;
static String CLRF = "\r\n";
public static void main(String[] args) throws IOException, InterruptedException {
final int numberOfCycles = 1000;
final int numbersPerCycle = 1000000;
final int NUM_CORES = Runtime.getRuntime().availableProcessors();
//Setup the running array
List<Integer> cyclesList = new LinkedList<Integer>();
for(int i = 0; i < numberOfCycles; i++){
cyclesList.add(i);
}
Stopwatch swG = new Stopwatch();
swG.start();
ExecutorService exec = Executors.newFixedThreadPool(NUM_CORES);
try {
for (final Integer x : cyclesList) {
exec.submit(new Runnable() {
@Override
public void run() {
System.out.printf("Starting cycle %s. Thread count at %s %s", x, threadCount++, CLRF);
Random r = new Random();
Stopwatch sw = new Stopwatch();
sw.start();
List<Double> numbers = new LinkedList<Double>();
for (int i = 0; i < numbersPerCycle; i++)
{
numbers.add(r.nextDouble() * 1000);
}
Collections.sort(numbers);
double min = Collections.min(numbers);
double max = Collections.max(numbers);
completeCount++;
System.out.printf("%s cycles complete: %.2f ms. Min: %.2f Max: %.2f %s", completeCount, sw.getElapsedTime(), min, max, CLRF);
threadCount--;
}
});
}
} finally {
exec.shutdown();
}
exec.awaitTermination(1, TimeUnit.DAYS);
System.out.printf("All %s cycles complete. Took %.2f ms. %s", numberOfCycles, swG.getElapsedTime(), CLRF);
System.out.println("Press any key to continue.");
System.in.read();
}
}
更新了 C# 版本以匹配答案中的 Java 版本
public class Program
{
static void Main(string[] args)
{
const int numberOfCycles = 1000;
const int numbersPerCycle = 1000000;
Stopwatch swG = Stopwatch.StartNew();
int threadCount = 0;
int completeCount = 0;
Parallel.For(0, numberOfCycles, x =>
{
Console.WriteLine(string.Format("Starting cycle {0}. Thread count at {1}", x, Interlocked.Increment(ref threadCount)));
Random r = new Random();
Stopwatch sw = Stopwatch.StartNew();
double[] numbers = new double[numbersPerCycle];
for (int i = 0; i < numbersPerCycle; i++)
{
numbers[i] = r.NextDouble() * 1000;
}
Array.Sort(numbers);
double min = numbers[0];
double max = numbers[numbers.Length - 1];
Interlocked.Increment(ref completeCount);
Console.WriteLine(string.Format("{0} cycles complete: {1:#,##0.0} ms. Min: {2:0.###} Max: {3:0.###}", completeCount, sw.ElapsedMilliseconds, min, max));
Interlocked.Decrement(ref threadCount);
});
Console.WriteLine(string.Format("All {0} cycles complete. Took {1:#,##0.0} ms.", numberOfCycles, swG.ElapsedMilliseconds));
Console.WriteLine("Press any key to continue.");
Console.ReadKey();
}
}