Browse Source

removed GetIndexedEnumerator from Vector - will add it back to the sparse Vector

moved the scaling factor and max block size from control into the Parallel class and made them constant

Signed-off-by: Marcus Cuda <marcus@cuda.net>
la-knuth
Marcus Cuda 17 years ago
parent
commit
914c317157
  1. 18
      src/Numerics/Control.cs
  2. 9
      src/Numerics/LinearAlgebra/Double/DenseVector.cs
  3. 94
      src/Numerics/LinearAlgebra/Double/Vector.cs
  4. 11
      src/Numerics/Threading/Parallel.cs
  5. 2
      src/Numerics/Threading/ThreadQueue.cs
  6. 28
      src/UnitTests/LinearAlgebraTests/Double/VectorTests.cs

18
src/Numerics/Control.cs

@ -44,8 +44,6 @@ namespace MathNet.Numerics
ThreadSafeRandomNumberGenerators = true;
DisableParallelization = false;
InitialThreadBlockSize = 2;
BlockScalingFactor = 2;
MaximumBlockSize = 1024;
}
/// <summary>
@ -85,21 +83,5 @@ namespace MathNet.Numerics
/// </summary>
/// <value>The initial size of the thread processing bloc.</value>
public static int InitialThreadBlockSize { get; set; }
/// <summary>
/// Gets or sets the <see cref="Parallel.ForEach{T}"/>
/// processing block scaling factor. With each iteration through
/// the for each loop, the processing block increased by this factor
/// up to <see cref="MaximumBlockSize"/>;
/// </summary>
/// <value>The processing block scaling factor.</value>
public static int BlockScalingFactor { get; set; }
/// <summary>
/// Gets or sets the maximum processing block size for
/// <see cref="Parallel.ForEach{T}"/>.
/// </summary>
/// <value>The maximum processing block size.</value>
public static int MaximumBlockSize { get; set; }
}
}

9
src/Numerics/LinearAlgebra/Double/DenseVector.cs

@ -98,10 +98,11 @@ namespace MathNet.Numerics.LinearAlgebra.Double
if (vector == null)
{
// using enumerators since they will be more efficient for copying sparse matrices
foreach (var item in other.GetIndexedEnumerator())
{
Data[item.Key] = item.Value;
}
// foreach (var item in other.GetIndexedEnumerator())
// {
// Data[item.Key] = item.Value;
// }
Parallel.For(0, Count, index => this[index] = other[index]);
}
else
{

94
src/Numerics/LinearAlgebra/Double/Vector.cs

@ -110,74 +110,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// </returns>
public abstract Vector CreateVector(int size);
/// <summary>
/// Returns an <see cref="IEnumerable{T}"/> that contains the position and value of the element.
/// </summary>
/// <returns>
/// An <see cref="IEnumerable{T}"/> over this vector that contains the position and value of each
/// non-zero element.
/// </returns>
/// <remarks>
/// The enumerator returns a
/// <seealso cref="KeyValuePair{T,K}"/>
/// with the key being the element index and the value
/// being the value of the element at that index. For sparse vectors, the enumerator will exclude all elements
/// with a zero value.
/// </remarks>
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures",
Justification = "Needed to support sparse vectors.")]
public virtual IEnumerable<KeyValuePair<int, double>> GetIndexedEnumerator()
{
for (var index = 0; index < Count; index++)
{
yield return new KeyValuePair<int, double>(index, this[index]);
}
}
/// <summary>
/// Returns an <see cref="IEnumerable{T}"/> over the specified elements.
/// </summary>
/// <param name="startIndex">
/// The element to start copying from.
/// </param>
/// <param name="length">
/// The number of elements to enumerate over.
/// </param>
/// <returns>
/// An <see cref="IEnumerable{T}"/> over a range of this vector.
/// </returns>
/// <exception cref="ArgumentOutOfRangeException">
/// If <paramref name="startIndex"/> or <paramref name="startIndex"/> + <paramref name="length"/>
/// is greater than the vector's length.
/// </exception>
/// <remarks>
/// The enumerator returns a
/// <seealso cref="KeyValuePair{T,K}"/>
/// with the key being the element index and the value
/// being the value of the element at that index.
/// </remarks>
/// <seealso cref="KeyValuePair{T,K}"/>
/// <seealso cref="IEnumerable{T}"/>
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures",
Justification = "Needed to support sparse vectors.")]
public virtual IEnumerable<KeyValuePair<int, double>> GetIndexedEnumerator(int startIndex, int length)
{
if (startIndex > Count)
{
throw new ArgumentOutOfRangeException("startIndex");
}
if (startIndex + length > Count)
{
throw new ArgumentOutOfRangeException("length");
}
for (var index = startIndex; index < length; index++)
{
yield return new KeyValuePair<int, double>(index, this[index]);
}
}
#region Elementary operations
/// <summary>
/// Adds a scalar to each element of the vector.
@ -333,11 +265,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <remarks>Added as an alternative to the unary negation operator.</remarks>
public virtual Vector Negate()
{
var result = CreateVector(Count);
Parallel.ForEach(GetIndexedEnumerator(), item => result[item.Key] = -item.Value);
return result;
return this * -1;
}
/// <summary>
@ -406,7 +334,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return;
}
Parallel.ForEach(GetIndexedEnumerator(), item => this[item.Key] = scalar * item.Value);
Parallel.For(0, Count, index => this[index] *= scalar);
}
/// <summary>
@ -681,11 +609,11 @@ namespace MathNet.Numerics.LinearAlgebra.Double
var sum = 0.0;
var syncLock = new object();
Parallel.ForEach(GetIndexedEnumerator(),
Parallel.For(0, Count,
()=> 0.0,
(pair, localData) =>
(index, localData) =>
{
localData += Math.Pow(Math.Abs(pair.Value), p);
localData += Math.Pow(Math.Abs(this[index]), p);
return localData;
},
localResult=>
@ -709,11 +637,11 @@ namespace MathNet.Numerics.LinearAlgebra.Double
{
var max = 0.0;
var syncLock = new object();
Parallel.ForEach(GetIndexedEnumerator(),
Parallel.For(0, Count,
() => 0.0,
(pair, localData) =>
(index, localData) =>
{
localData = Math.Max(localData, Math.Abs(pair.Value));
localData = Math.Max(localData, Math.Abs(this[index]));
return localData;
},
localResult =>
@ -788,8 +716,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
{
return;
}
Parallel.ForEach(GetIndexedEnumerator(), item => target[item.Key] = item.Value);
Parallel.For(0, Count, index => target[index] = this[index]);
}
/// <summary>
@ -890,9 +817,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <returns>
/// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
/// </returns>
/// <remarks>
/// For sparse vectors, <see cref="GetIndexedEnumerator()"/> will perform better.
/// </remarks>
public virtual IEnumerator<double> GetEnumerator()
{
for (var index = 0; index < Count; index++)

11
src/Numerics/Threading/Parallel.cs

@ -38,6 +38,9 @@ namespace MathNet.Numerics.Threading
/// </summary>
internal static class Parallel
{
private const int ScalingFactor = 2;
private const int MaxBlockSize = 65536;
/// <summary>
/// Executes a for loop in which iterations may run in parallel.
/// </summary>
@ -220,7 +223,7 @@ namespace MathNet.Numerics.Threading
var enumerator = source.GetEnumerator();
var maxBlockSize = Control.InitialThreadBlockSize;
var scalingFactor = Control.BlockScalingFactor;
var scalingFactor = ScalingFactor;
var tasks = new List<Task>();
while (enumerator.MoveNext())
{
@ -246,7 +249,7 @@ namespace MathNet.Numerics.Threading
ThreadQueue.Enqueue(task);
tasks.Add(task);
maxBlockSize = Math.Min(Control.MaximumBlockSize, maxBlockSize * scalingFactor);
maxBlockSize = Math.Min(MaxBlockSize, maxBlockSize * scalingFactor);
}
if (tasks.Count > 0)
@ -275,7 +278,7 @@ namespace MathNet.Numerics.Threading
var enumerator = source.GetEnumerator();
var maxBlockSize = Control.InitialThreadBlockSize;
var scalingFactor = Control.BlockScalingFactor;
var scalingFactor = ScalingFactor;
var tasks = new List<Task<TLocal>>();
var intial = localInit();
@ -306,7 +309,7 @@ namespace MathNet.Numerics.Threading
ThreadQueue.Enqueue(task);
tasks.Add(task);
maxBlockSize = Math.Min(Control.MaximumBlockSize, maxBlockSize * scalingFactor);
maxBlockSize = Math.Min(MaxBlockSize, maxBlockSize * scalingFactor);
}
if (tasks.Count <= 0)

2
src/Numerics/Threading/ThreadQueue.cs

@ -55,7 +55,7 @@ namespace MathNet.Numerics.Threading
/// <summary>
/// Maximum number of jobs that can be in the queue at the same time.
/// </summary>
private const int MaximumQueueLength = 1024;
private const int MaximumQueueLength = 4096;
/// <summary>
/// Counting Semaphore to make the worker thread wait for jobs

28
src/UnitTests/LinearAlgebraTests/Double/VectorTests.cs

@ -121,34 +121,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
Assert.IsFalse(vector1.Equals(null));
}
[Test]
[MultipleAsserts]
public void CanGetIndexedEnumerator()
{
var vector = CreateVector(_data);
var index = 0;
foreach (var pair in vector.GetIndexedEnumerator())
{
Assert.AreEqual(index, pair.Key);
Assert.AreEqual(++index, pair.Value);
}
}
[Test]
[MultipleAsserts]
public void CanGetIndexedEnumeratorOverRange()
{
var vector = CreateVector(_data);
var index = 2;
foreach (var pair in vector.GetIndexedEnumerator(2, 2))
{
Assert.AreEqual(index, pair.Key);
Assert.AreEqual(++index, pair.Value);
}
}
[Test]
[MultipleAsserts]
public void ThrowsArgumentExceptionIfSizeIsNotPositive()

Loading…
Cancel
Save