Практическое руководство. Написание пользовательской агрегатной функции PLINQ
В этом примере показано использование метода Aggregate для применения пользовательской функции агрегирования к исходной последовательности.
Внимание |
---|
Этот пример демонстрирует использование и может выполняться медленнее, чем аналогичный последовательный запрос LINQ to Objects.Дополнительные сведения об увеличении скорости см. в разделе Общее представление об ускорении выполнения в PLINQ. |
Пример
В следующем примере вычисляется стандартное отклонение последовательности целых чисел.
Class aggregation
Private Shared Sub Main(ByVal args As String())
' Create a data source for demonstration purposes.
Dim source As Integer() = New Integer(99999) {}
Dim rand As New Random()
For x As Integer = 0 To source.Length - 1
' Should result in a mean of approximately 15.0.
source(x) = rand.[Next](10, 20)
Next
' Standard deviation calculation requires that we first
' calculate the mean average. Average is a predefined
' aggregation operator, along with Max, Min and Count.
Dim mean As Double = source.AsParallel().Average()
' We use the overload that is unique to ParallelEnumerable. The
' third Func parameter combines the results from each thread.
' initialize subtotal. Use decimal point to tell
' the compiler this is a type double. Can also use: 0d.
' do this on each thread
' aggregate results after all threads are done.
' perform standard deviation calc on the aggregated result.
Dim standardDev As Double = source.AsParallel().Aggregate(0.0R, Function(subtotal, item) subtotal + Math.Pow((item - mean), 2), Function(total, thisThread) total + thisThread, Function(finalSum) Math.Sqrt((finalSum / (source.Length - 1))))
Console.WriteLine("Mean value is = {0}", mean)
Console.WriteLine("Standard deviation is {0}", standardDev)
Console.ReadLine()
End Sub
End Class
namespace PLINQAggregation
{
using System;
using System.Linq;
class aggregation
{
static void Main(string[] args)
{
// Create a data source for demonstration purposes.
int[] source = new int[100000];
Random rand = new Random();
for (int x = 0; x < source.Length; x++)
{
// Should result in a mean of approximately 15.0.
source[x] = rand.Next(10, 20);
}
// Standard deviation calculation requires that we first
// calculate the mean average. Average is a predefined
// aggregation operator, along with Max, Min and Count.
double mean = source.AsParallel().Average();
// We use the overload that is unique to ParallelEnumerable. The
// third Func parameter combines the results from each thread.
double standardDev = source.AsParallel().Aggregate(
// initialize subtotal. Use decimal point to tell
// the compiler this is a type double. Can also use: 0d.
0.0,
// do this on each thread
(subtotal, item) => subtotal + Math.Pow((item - mean), 2),
// aggregate results after all threads are done.
(total, thisThread) => total + thisThread,
// perform standard deviation calc on the aggregated result.
(finalSum) => Math.Sqrt((finalSum / (source.Length - 1)))
);
Console.WriteLine("Mean value is = {0}", mean);
Console.WriteLine("Standard deviation is {0}", standardDev);
Console.ReadLine();
}
}
}
В этом примере используется перегрузка стандартного оператора запроса Aggregate, уникального для PLINQ. Эта перегрузка принимает дополнительный делегат System.Func<T1, T2, TResult> как третий входной параметр. Этот делегат объединяет результаты из всех потоков перед выполнением окончательного расчета согласно агрегированным результатам. В этом примере складываются суммы из всех потоков.
Обратите внимание, что тело лямбда-выражения состоит из одного выражения, а возвращаемым значением делегата System.Func<T, TResult> является значение выражения.
См. также
Ссылки
Основные понятия
Журнал изменений
Дата |
Журнал |
Причина |
---|---|---|
Май 2010 |
Добавлено примечание о сравнении использования и ускорения. |
Обратная связь от клиента. |