Tôi đã viết một số mã mẫu cơ bản để tự làm quen với PLINQ.Tại sao truy vấn PLINQ AsOrdered của tôi lại nhanh hơn số
Tôi đã gặp phải điều gì đó kỳ lạ. Tôi không biết nếu đó là một lỗi trong mã của tôi hoặc một lỗi trong sự hiểu biết của tôi về PLINQ.
Tài liệu MSDN nói rằng việc thêm AsOrdered() sẽ duy trì thứ tự cuộc gọi với chi phí hiệu suất có thể.
Tôi đã viết một số kiểm tra đơn vị và nhận thấy hiệu ứng trên đơn đặt hàng trên tập kết quả như đã nêu trong tài liệu. Nhưng tôi đã thấy hiệu ứng nghịch đảo về hiệu suất.
Dưới đây là cả hai phương pháp của tôi:
public IEnumerable<int> ParallelCalculatePrimesUpTo(int maxValue)
{
return from number in Enumerable.Range(1, maxValue).AsParallel()
where IsPrime(number)
select number;
}
public IEnumerable<int> OrderedParallelCalculatePrimesUpTo(int maxValue)
{
return from number in Enumerable.Range(1, maxValue).AsParallel().AsOrdered()
where IsPrime(number)
select number;
}
Và tiêu chuẩn rất đơn giản của tôi
[TestMethod]
public void SimplisticBenchmark6()
{
var primeNumberCalculator = new PrimeNumberCalculator();
var startTime = DateTime.Now;
primeNumberCalculator.ParallelCalculatePrimesUpTo(10000000).ToList();
var totalTime = DateTime.Now - startTime;
Console.WriteLine(totalTime);
}
[TestMethod]
public void SimplisticBenchmark7()
{
var primeNumberCalculator = new PrimeNumberCalculator();
var startTime = DateTime.Now;
primeNumberCalculator.OrderedParallelCalculatePrimesUpTo(10000000).ToList();
var totalTime = DateTime.Now - startTime;
Console.WriteLine(totalTime);
}
Không có vấn đề bao lâu thì tôi chạy thử nghiệm này, các phiên bản ra lệnh nhịp đập ra một thứ tự. Tôi nhận được khoảng 4 giây nhanh hơn cho một thứ tự trên máy tính lõi tứ của tôi. Tôi nhận được khoảng 18 giây cho một thứ tự và 22 giây cho người không có thứ tự. Tôi đã chạy thử nghiệm hàng chục lần trong thời gian hai ngày (với khởi động lại giữa những ngày đó).
Nếu tôi hạ thấp số từ 10 000 000 xuống 6 000 000, sự khác biệt vẫn còn ở đó nhưng ít đáng chú ý hơn và nếu tôi hạ thấp xuống còn 3 000 000, nó sẽ có cùng tốc độ.
Tôi đã thử chạy thử nghiệm theo cả hai thứ tự thực thi và kết quả giống nhau.
Dưới đây là phương pháp isPrime đó được gọi là trong truy vấn PLINQ:
// uses inneficient trial division algorithm
private bool IsPrime(int number)
{
if (number == 1)
return false;
for (int divisor = 2; divisor <= Math.Sqrt(number); divisor++)
{
if (number % divisor == 0)
return false;
}
return true;
}
Điều này giải thích?
Như một lưu ý phụ, 'DateTime' không phải là rất tốt cho phép đo hiệu suất, sử dụng' StopWatch' là tốt hơn. – svick
@svick: Rất tốt. Tôi biết DateTime không tốt cho các phép đo nghiêm trọng nhưng không biết về StopWatch. Cảm ơn. Đối với mã sản xuất nó tốt hơn để sử dụng một hồ sơ, nhưng điều này chỉ là mã nhanh chóng và bẩn tôi đã viết khi tôi đọc PLINQ và TPL doc. Lần tới tôi sẽ sử dụng StopWatch trong tình huống như vậy! – Gilles
Nếu tôi chạy mã của bạn, đặt hàng hơi chậm hơn (5,67 s so với 5,66 s cho không có thứ tự, trung bình trong một số lần thử), nhưng chênh lệch giữa các lần thử cao hơn sự khác biệt giữa thứ tự và không có thứ tự, vì vậy tôi nghĩ rằng không có sự khác biệt có ý nghĩa thống kê trong trường hợp này (ít nhất là được đo trên lõi tứ của tôi). – svick