Is there anyway to "vectorize" the addition of elements across arrays in a SIMD fashion?
For example, I would like to turn:
var a = new[] { 1, 2, 3, 4 };
var b = new[] { 1, 2, 3, 4 };
var c = new[] { 1, 2, 3, 4 };
var d = new[] { 1, 2, 3, 4 };
var e = new int[4];
for (int i = 0; i < a.Length; i++)
{
e[i] = a[i] + b[i] + c[i] + d[i];
}
// e should equal { 4, 8, 12, 16 }
Into something like:
var e = VectorAdd(a,b,c,d);
I know something may exist in the C++ / XNA libraries, but I didn't know if we have it in the standard .Net libraries.
Thanks!
You will want to look at Mono.Simd:
http://tirania.org/blog/archive/2008/Nov-03.html
It supports SIMD in C#
using Mono.Simd;
//...
var a = new Vector4f( 1, 2, 3, 4 );
var b = new Vector4f( 1, 2, 3, 4 );
var c = new Vector4f( 1, 2, 3, 4 );
var d = new Vector4f( 1, 2, 3, 4 );
var e = a+b+c+d;
Mono provides a relatively decent SIMD API (as sehe mentions) but if Mono isn't an option I would probably write a C++/CLI interface library to do the heavy lifting. C# works pretty well for most problem sets but if you start getting into high performance code it's best to go to a language that gives you the control to really get dirty with performance.
Here at work we use P/Invoke to call image processing routines written in C++ from C#. P/Invoke has some overhead but if you make very few calls and do a lot of processing on the native side it can be worth it.
I guess it all depends on what you are doing, but if you are worried about vectorizing vector sums, you might want to take a look at a library such as Math.NET which provide optimized numerical computations.
From their website:
It targets Microsoft .Net 4.0, Mono and Silverlight 4, and in addition to a purely managed implementation will also support native hardware optimization (MKL, ATLAS).
Related
I recently learned that you import functions from the F# core library to C# such as
using Microsoft.FSharp.Core
...
var max = new List<int>() { 1, 2, 3 }.Aggregate(int.MinValue, Operators.Max);
Is there an equivalent function available for addition? I can't seem to find one. It would be cool to be able to write
var sum = new List<int>() { 1, 2, 3 }.Aggregate(0, Operators.Add);
There is an addition operator in Operators: Operators.( + )
You can consume it from C# using this:
var sum = new List<int>() { 1, 2, 3 }.Aggregate(0, Operators.op_Addition<int, int, int>);
How to perform Change Point Analysis using R.NET. I am using below code
REngine.SetEnvironmentVariables();
REngine engine = REngine.GetInstance();
double[] data = new double[] { 1, 2, 3, 4, 5, 6 };
NumericVector vector = engine.CreateNumericVector(data);
engine.SetSymbol("mydatapoints", vector);
engine.Evaluate("library(changepoint)");
engine.Evaluate("chpoints = cpt.mean(mydatapoints, method="BinSeg")");
DynamicVector result = engine.Evaluate("x<-cpts(chpoints)").AsVector(); ;
engine.Dispose();
I am receiving below error on engine.Evaluate("library(changepoint)");
Error in library(changepoint) : there is no package called
'changepoint'
Edit # 1
The changepoint package is supposed to be installed explicitly, it is not there by default. Installed it using RGui -> Packages -> Load package.
Now the error has been changed to
Status Error for chpoints = cpt.mean(mydatapoints, method=”BinSeg”) :
unexpected input
Edit # 2
After fixing first two errors, the following one appears on second Evaluate statement.
Error in BINSEG(sumstat, pen = pen.value, cost_func = costfunc,
minseglen = minseglen, : Q is larger than the maximum number of
segments 4
The same error appears on R as well using these commands
value.ts <- c(29.89, 29.93, 29.72, 29.98)
chpoints = cpt.mean(value.ts, method="BinSeg")
The error is not in your calling code but rather in your use of R (as you apparently now realize.) So the labeling of this as something to do with rdotnet or c-sharp seems misleading:
mydatapoints <- c(1, 2, 3, 4, 5, 6 )
library(changepoint);
chpoints = cpt.mean(mydatapoints, method="BinSeg");
#Error in BINSEG(sumstat, pen = pen.value, cost_func = costfunc, minseglen = minseglen, :
# Q is larger than the maximum number of segments 4
I'm not sure what you intended. Change-point analysis generally requires paired datapoints ... x-y and all that jazz. And giving R regression functions perfectly linear data is also unwise. It often causes non-invertible matrices.
I suggest you search with https://stackoverflow.com/search?q=%5Br%5D+changepoint to find a simple bit of code to build into your REngine calling scheme.
The data points are supposed to be converted in Time Series.
REngine.SetEnvironmentVariables();
REngine engine = REngine.GetInstance();
double[] data = new double[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
NumericVector vector = engine.CreateNumericVector(data);
engine.Evaluate("library(changepoint)");
engine.SetSymbol("values", vector);
engine.Evaluate("values.ts = ts(values, frequency = 12, start = c(2017, 1))");
engine.Evaluate("chpoints = cpt.mean(values.ts, method=\"BinSeg\")");
var result = engine.GetSymbol("chpoints");
engine.Dispose();
Now looking for how to get the results back in C#, chpoints or result of plot(chpoints)
There must be an better way to do this, I'm sure...
// Simplified code
var a = new List<int>() { 1, 2, 3, 4, 5, 6 };
var b = new List<int>() { 2, 3, 5, 7, 11 };
var z = new List<int>();
for (int i = 0; i < a.Count; i++)
if (b.Contains(a[i]))
z.Add(a[i]);
// (z) contains all of the numbers that are in BOTH (a) and (b), i.e. { 2, 3, 5 }
I don't mind using the above technique, but I want something fast and efficient (I need to compare very large Lists<> multiple times), and this appears to be neither! Any thoughts?
Edit: As it makes a difference - I'm using .NET 4.0, the initial arrays are already sorted and don't contain duplicates.
You could use IEnumerable.Intersect.
var z = a.Intersect(b);
which will probably be more efficient than your current solution.
note you left out one important piece of information - whether the lists happen to be ordered or not. If they are then a couple of nested loops that pass over each input array exactly once each may be faster - and a little more fun to write.
Edit
In response to your comment on ordering:
first stab at looping - it will need a little tweaking on your behalf but works for your initial data.
int j = 0;
foreach (var i in a)
{
int x = b[j];
while (x < i)
{
if (x == i)
{
z.Add(b[j]);
}
j++;
x = b[j];
}
}
this is where you need to add some unit tests ;)
Edit
final point - it may well be that Linq can use SortedList to perform this intersection very efficiently, if performance is a concern it is worth testing the various solutions. Dont forget to take the sorting into account if you load your data in an un-ordered manner.
One Final Edit because there has been some to and fro on this and people may be using the above without properly debugging it I am posting a later version here:
int j = 0;
int b1 = b[j];
foreach (var a1 in a)
{
while (b1 <= a1)
{
if (b1 == a1)
z1.Add(b[j]);
j++;
if (j >= b.Count)
break;
b1 = b[j];
}
}
There's IEnumerable.Intersect, but since this is an extension method, I doubt it will be very efficient.
If you want efficiency, take one list and turn it into a Set, then go over the second list and see which elements are in the set. Note that I preallocate z, just to make sure you don't suffer from any reallocations.
var set = new HashSet<int>(a);
var z = new List<int>(Math.Min(set.Count, b.Count));
foreach(int i in b)
{
if(set.Contains(i))
a.Add(i);
}
This is guaranteed to run in O(N+M) (N and M being the sizes of the two lists).
Now, you could use set.IntersectWith(b), and I believe it will be just as efficient, but I'm not 100% sure.
The Intersect() method does just that. From MSDN:
Produces the set intersection of two sequences by using the default
equality comparer to compare values.
So in your case:
var z = a.Intersect(b);
Use SortedSet<T> in System.Collections.Generic namespace:
SortedSet<int> a = new SortedSet<int>() { 1, 2, 3, 4, 5, 6 };
SortedSet<int> b = new SortedSet<int>() { 2, 3, 5, 7, 11 };
b.IntersectWith(s2);
But surely you have no duplicates!
Although your second list needs not to be a SortedSet. It can be any collection (IEnumerable<T>), but internally the method act in a way that if the second list also is SortedSet<T>, the operation is an O(n) operation.
If you can use LINQ, you could use the Enumerable.Intersect() extension method.
For C# in VS2005, can you do something like this:
if number in [1,2..10,12] { ... }
which would check if number is contained in the set defined in the square brackets?
.NET 2.0 (which is what VS 2005 targets) doesn't have the notion of a Set.
.NET 3.5 introduced HashSet<T>, and .NET 4 introduced SortedSet<T>.
There isn't a literal form for them though - although collection initializers provide something slightly similar:
new HashSet<int> { 1, 2, 4, 12 }
Of course, you could just use an array:
int[] values = { 1, 2, 5, 12 };
but the range part of your sample - 2..10 - doesn't exist in any version of C#.
Unfortunately not.
However, you can use the Contains() method of a List<int>:
List<int> numbers = ...
if (numbers.Contains(2)) { ... }
if numbers is an array, you can either initialize a new List<int> with the array values:
int[] numbers = { 1, 2, 3, 4 };
List<int> newList = new List<int>(numbers);
if (newList.Contains(2)) { ... }
or use Array.Exists():
Array.Exists(numbers, delegate(int i) { return i == 2; });
You can "kind of" do what you want using the Enumerable.Range method:
if (Enumerable.Range(2, 8).Concat(new [] { 1, 12 }).Contains(number)) {
....
}
Of course, that's not nearly as readable as what you find in a basic functional language...
Let's say that I have an array of strings like this:
1, 2, 3, 4, 5, 6, 7, 8
and I want to shift the elements of the array such that
The first element always remains fixed
Only the remaining elements get shifted like so ...
The last element in the array becomes the 2nd element and is shifted through the array with each pass.
Pass #1: 1, 2, 3, 4, 5, 6, 7, 8
Pass #2: 1, 8, 2, 3, 4, 5, 6, 7
Pass #3: 1, 7, 8, 2, 3, 4, 5, 6
Pass #4: 1, 6, 7, 8, 2, 3, 4, 5
Any assistance would be greatly appreciated.
Because this looks like homework, I'm posting an unnecessary complex, but very hip LINQ solution:
int[] array = new int[] { 1, 2, 3, 4, 5, 6, 7, 8 };
int[] result = array.Take(1)
.Concat(array.Reverse().Take(1))
.Concat(array.Skip(1).Reverse().Skip(1).Reverse())
.ToArray();
Probably the fastest way to do this in C# is to use Array.Copy. I don't know much about pointers in C# so there's probably a way of doing it that's even faster and avoids the array bounds checks and such but the following should work. It makes several assumptions and doesn't check for errors but you can fix it up.
void Shift<T>(T[] array) {
T last = array[array.Length-1];
Array.Copy(array, 1, array, 2, array.Length-2);
array[1]=last;
}
EDIT
Optionally, there is Buffer.BlockCopy which according to this post performs fewer validations but internally copies the block the same way.
Because this looks like homework, I'm not going to solve it for you, but I have a couple of suggestions:
Remember to not overwrite data if it isn't somewhere else already. You're going to need a temporary variable.
Try traversing the array from the end to the beginning. The problem is probably simpler that way, though it can be done from front-to-back.
Make sure your algorithm works for an arbitrary-length array, not just one that's of size 8, as your example gave.
Although sounds like homework like others suggest, if changing to a List<>, you can get what you want with the following...
List<int> Nums2 = new List<int>();
for( int i = 1; i < 9; i++ )
Nums2.Add(i);
for (int i = 1; i < 10; i++)
{
Nums2.Insert( 1, Nums2[ Nums2.Count -1] );
Nums2.RemoveAt(Nums2.Count -1);
}
Define this:
public static class Extensions
{
public static IEnumerable<T> Rotate<T>(this IEnumerable<T> enuml)
{
var count = enuml.Count();
return enuml
.Skip(count - 1)
.Concat(enuml.Take(count - 1));
}
public static IEnumerable<T> SkipAndRotate<T>(this IEnumerable<T> enuml)
{
return enum
.Take(1)
.Concat(
enuml.Skip(1).Rotate()
);
}
}
Then call it like so:
var array = new [] { 1, 2, 3, 4, 5, 6, 7, 8 };
var pass1 = array.SkipAndRotate().ToArray();
var pass2 = pass1.SkipAndRotate().ToArray();
var pass3 = pass2.SkipAndRotate().ToArray();
var pass4 = pass3.SkipAndRotate().ToArray();
There's some repeated code there that you might want to refactor. And of course, I haven't compiled this so caveat emptor!
This is similar to Josh Einstein's but it will do it manually and will allow you to specify how many elements to preserve at the beginning.
static void ShiftArray<T>(T[] array, int elementsToPreserve)
{
T temp = array[array.Length - 1];
for (int i = array.Length - 1; i > elementsToPreserve; i--)
{
array[i] = array[i - 1];
}
array[elementsToPreserve] = temp;
}
Consumed:
int[] array = { 1, 2, 3, 4, 5, 6, 7, 8 };
ShiftArray(array, 2);
First pass: 1 2 8 3 4 5 6 7