Operacja polega na pomnożeniu każdego i-tego elementu tablicy (nazwij go A) i i-tego elementu macierzy o tym samym rozmiarze (B) i aktualizować ten sam i-ty element A z uzyskaną wartością.Jak mogę zmaksymalizować wydajność operacji element-mądry na dużej tablicy w C#
W arytmetyczna wzorze A '[i] = A [b] x B [I] (0 < i < n (A))
Co najlepszy sposób zoptymalizować działanie w multi -reklama środowiska?
Oto mój obecny kod;
var learningRate = 0.001f;
var m = 20000;
var n = 40000;
var W = float[m*n];
var C = float[m*n];
//my current code ...[1]
Parallel.ForEach(Enumerable.Range(0, m), i =>
{
for (int j = 0; j <= n - 1; j++)
{
W[i*n+j] *= C[i*n+j];
}
});
//This is somehow far slower than [1], but I don't know why ... [2]
Parallel.ForEach(Enumerable.Range(0, n*m), i =>
{
w[i] *= C[i]
});
//This is faster than [2], but not as fast as [1] ... [3]
for(int i = 0; i < m*n; i++)
{
w[i] *= C[i]
}
Przetestowano następujące metody. Ale występ wcale się nie poprawił. http://msdn.microsoft.com/en-us/library/dd560853.aspx
public static void Test1()
{
Random rnd = new Random(1);
var sw1 = new Stopwatch();
var sw2 = new Stopwatch();
sw1.Reset();
sw2.Reset();
int m = 10000;
int n = 20000;
int loops = 20;
var W = DummyDataUtils.CreateRandomMat1D(m, n);
var C = DummyDataUtils.CreateRandomMat1D(m, n);
for (int l = 0; l < loops; l++)
{
var v = DummyDataUtils.CreateRandomVector(n);
var b = DummyDataUtils.CreateRandomVector(m);
sw1.Start();
Parallel.ForEach(Enumerable.Range(0, m), i =>
{
for (int j = 0; j <= n - 1; j++)
{
W[i*n+j] *= C[i*n+j];
}
});
sw1.Stop();
sw2.Start();
// Partition the entire source array.
var rangePartitioner = Partitioner.Create(0, n*m);
// Loop over the partitions in parallel.
Parallel.ForEach(rangePartitioner, (range, loopState) =>
{
// Loop over each range element without a delegate invocation.
for (int i = range.Item1; i < range.Item2; i++)
{
W[i] *= C[i];
}
});
sw2.Stop();
Console.Write("o");
}
var t1 = (double)sw1.ElapsedMilliseconds/loops;
var t2 = (double)sw2.ElapsedMilliseconds/loops;
Console.WriteLine("t1: " + t1);
Console.WriteLine("t2: " + t2);
}
Wynik:
t1: 119
t2: 120,4
Moje zrozumienie jest [1] jest najbardziej zoptymalizowane, ponieważ [2] tworzy zbyt wiele kolejek, co zwiększa koszty dodatkowego przetwarzania i alokowania zadań, aby uwolnić wątki zmniejszające wydajność, podczas gdy [3] działa na pojedynczy wątek, więc brak równoległości. Ale [1] najlepiej sprawdza się w obu przypadkach, tzn. Równolegle, aby wykorzystać wielordzeniowe/wątki i jeszcze niezbyt wiele kolejek do przetworzenia. –
Optymalizacja mikro, jak rozwijanie pętli może pomóc tutaj. – leppie
Uruchamianie i zatrzymywanie stopera w pętli nie będzie bardzo dokładne. – leppie