C# Error in constructor of a class - c#

I try to randomize the values if they are not changed, but it won't let me use the randomizer in the constructor and it gives an error when I use my other function.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Randomizer {
class Apartment {
public int height;
public int bas;
public int hasPent;
public Apartment(int b = 100, int h = 100, int p = 100) {
height = h;
bas = b;
hasPent = p;
public Room[,,] rooms = new Room[bas, bas, height];
finCon(bas, height, hasPent, rooms);
}
void finCon(int b, int h, int p, Room[,,] ro) {
Random r = new Random();
if (b==100) {
b = r.Next(2,4);
}
if (h==100) {
h = r.Next(4,15);
}
if (p==100) {
p = r.Next(0,20);
}
}
}
class Room {
int some = 37;
}
class Program {
static void Main(string[] args)
{
Apartment ap = new Apartment();
ap.finCon(ap.bas,ap.height,ap.hasPent,ap.rooms);
Console.WriteLine("{0}{1}",ap.bas,ap.height);
}
}
}
Errors:
(1:1) A namespace cannot directly contain members such as fields or methods
(16:25) } expected
(18:13) Method must have a return type
(18:23) Identifier expected
(18:31) Identifier expected
(18:40) Identifier expected
(18:47) Identifier expected
(21:9) A namespace cannot directly contain members such as fields or methods
(21:47) Identifier expected
(21:48) Identifier expected
(21:51) Expected class, delegate, enum, interface, or struct
(22:28) Expected class, delegate, enum, interface, or struct
(33:5) Type or namespace definition, or end-of-file expected
(46:1) Type or namespace definition, or end-of-file expected

I've made it compile:
namespace Randomizer
{
public class Apartment
{
public int height;
public int bas;
public int hasPent;
public Room[,,] rooms;
public Apartment(int b = 100, int h = 100, int p = 100)
{
height = h;
bas = b;
hasPent = p;
rooms = new Room[bas, bas, height];
finCon(bas, height, hasPent, rooms);
}
public void finCon(int b, int h, int p, Room[,,] ro)
{
Random r = new Random();
if (b == 100)
{
b = r.Next(2, 4);
}
if (h == 100)
{
h = r.Next(4, 15);
}
if (p == 100)
{
p = r.Next(0, 20);
}
}
}
public class Room
{
int some = 37;
}
class Program
{
static void Main(string[] args)
{
Apartment ap = new Apartment();
ap.finCon(ap.bas, ap.height, ap.hasPent, ap.rooms);
Console.WriteLine("{0}{1}", ap.bas, ap.height);
}
}
}
Your problem is trying to declare a property inside the constructor (you can't do it). I've made all classes public too.
Hope it will help you.

Related

Generalize deserializing from byte array

I am parsing a byte array containing different type values stored in a fixed format. For example first 4 bytes could be an int containing size of an array -
let's say the array of doubles so next 8 bytes represent a double - the first element of the array etc. It could in theory contain values of other types, but let's say we can only have
bool,int,uint,short,ushort,long,ulong,float,double and arrays of each of these. Simple approach:
public class FixedFormatParser
{
private byte[] _Contents;
private int _CurrentPos = 0;
public FixedFormatParser(byte[] contents)
{
_Contents = contents;
}
bool ReadBool()
{
bool res = BitConverter.ToBoolean(_Contents, _CurrentPos);
_CurrentPos += sizeof(bool);
return res;
}
int ReadInt()
{
int res = BitConverter.ToInt32(_Contents, _CurrentPos);
_CurrentPos += sizeof(int);
return res;
}
// etc. for uint, short, ushort, long, ulong, float, double
int[] ReadIntArray()
{
int size = ReadInt();
if (size == 0)
return null;
int[] res = new int[size];
for (int i = 0; i < size; i++)
res[i] = ReadInt();
return res;
}
// etc. for bool, uint, short, ushort, long, ulong, float, double
}
I can obviously write 18 methods to cover each case, but seems like there should be a way to generalize this.
bool val = Read<bool>();
long[] arr = ReadArray<long>(); // or ReadArray(Read<long>);
Obviously I don't mean write 2 wrappers in addition to the 18 methods to allow for this syntax. The syntax is not important, the code duplication is the issue. Another consideration is the performance. Ideally there would not be any (or much) of a performance hit. Thanks.
Update:
Regarding other questions that are supposedly duplicates. I disagree as none of them addressed the particular generalization I am after, but one came pretty close:
First answer in
C# Reading Byte Array
described wrapping BinaryReader. This would cover 9 of the 18 methods. So half of the problem is addressed. I still would need to write all of the various array reads.
public class FixedFormatParser2 : BinaryReader
{
public FixedFormatParser2(byte[] input) : base(new MemoryStream(input))
{
}
public override string ReadString()
{
//
}
public double[] ReadDoubleArray()
{
int size = ReadInt32();
if (size == 0)
return null;
double[] res = new double[size];
for (int i = 0; i < size; i++)
res[i] = ReadDouble();
return res;
}
}
How do I not write a separate ReadXXXArray for each of the types?
Nearest I got to it:
public void WriteCountedArray(dynamic[] input)
{
if (input == null || input.Length == 0)
Write((int)0);
else
{
Write(input.Length);
foreach (dynamic val in input)
Write(val);
}
}
This compiles but calling it is cumbersome and expensive :
using (FixedFormatWriter writer = new FixedFormatWriter())
{
double[] array = new double[3];
// ... assign values
writer.WriteCountedArray(array.Select(x=>(dynamic)x).ToArray());
I like doing like this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication50
{
class Program
{
static void Main(string[] args)
{
new Format();
}
}
public class Format
{
public enum TYPES
{
INT,
INT16,
LONG
}
public static List<Format> format = new List<Format>() {
new Format() { name = "AccountNumber", _type = TYPES.INT ,numberOfBytes = 4},
new Format() { name = "Age", _type = TYPES.INT16 ,numberOfBytes = 2},
new Format() { name = "AccountNumber", _type = TYPES.LONG ,numberOfBytes = 8}
};
public Dictionary<string, object> dict = new Dictionary<string, object>();
public string name { get; set; }
public TYPES _type { get; set; }
public int numberOfBytes { get; set; }
public Format() { }
public Format(byte[] contents)
{
MemoryStream stream = new MemoryStream(contents);
BinaryReader reader = new BinaryReader(stream);
foreach (Format item in format)
{
switch (item._type)
{
case TYPES.INT16 :
dict.Add(item.name, reader.ReadInt16());
break;
case TYPES.INT:
dict.Add(item.name, reader.ReadInt32());
break;
case TYPES.LONG:
dict.Add(item.name, reader.ReadInt64());
break;
}
}
}
}
}

clrobj(<class name>) does not have llvm when passing array of struct to GPU Kernel (ALEA Library)

I am getting the "Fody/Alea.CUDA: clrobj(cGPU) does not have llvm" build error for a code in which I try to pass an array of struct to the NVIDIA Kernel using ALEA library. Here is a simplified version of my code. I removed the output gathering functionality in order to keep the code simple. I just need to be able to send the array of struct to the GPU for the moment.
using Alea.CUDA;
using Alea.CUDA.Utilities;
using Alea.CUDA.IL;
namespace GPUProgramming
{
public class cGPU
{
public int Slice;
public float FloatValue;
}
[AOTCompile(AOTOnly = true)]
public class TestModule : ILGPUModule
{
public TestModule(GPUModuleTarget target) : base(target)
{
}
const int blockSize = 64;
[Kernel]
public void Kernel2(deviceptr<cGPU> Data, int n)
{
var start = blockIdx.x * blockDim.x + threadIdx.x;
int ind = threadIdx.x;
var sharedSlice = __shared__.Array<int>(64);
var sharedFloatValue = __shared__.Array<float>(64);
if (ind < n && start < n)
{
sharedSlice[ind] = Data[start].Slice;
sharedFloatValue[ind] = Data[start].FloatValue;
Intrinsic.__syncthreads();
}
}
public void Test2(deviceptr<cGPU> Data, int n, int NumOfBlocks)
{
var GridDim = new dim3(NumOfBlocks, 1);
var BlockDim = new dim3(64, 1);
try
{
var lp = new LaunchParam(GridDim, BlockDim);
GPULaunch(Kernel2, lp, Data, n);
}
catch (CUDAInterop.CUDAException x)
{
var code = x.Data0;
Console.WriteLine("ErrorCode = {0}", code);
}
}
public void Test2(cGPU[] Data)
{
int NumOfBlocks = Common.divup(Data.Length, blockSize);
using (var d_Slice = GPUWorker.Malloc(Data))
{
try
{
Test_Kernel2(d_Slice.Ptr, Data.Length, NumOfBlocks);
}
catch (CUDAInterop.CUDAException x)
{
var code = x.Data0;
Console.WriteLine("ErrorCode = {0}", x.Data0);
}
}
}
}
}
Your data is class, which is reference type. Try use struct. Reference type doesn't fit Gpu well, since it require of allocating small memory on the heap.

Serialize class with structs of same type name

I'm trying to XML serialize a class that contains two structs with the same name:
public class MyClass
{
public System.Windows.Size WSize = new System.Windows.Size();
public System.Drawing.Size DSize = new Size.Drawing.Size();
}
The resulting error:
Types 'System.Drawing.Size' and 'System.Windows.Size' both use the XML type name,
'Size', from namespace ''. Use XML attributes to specify a unique XML name and/or
namespace for the type.
Everything I've found so far involves decorating the Type with an XML attribute. I can't directly decorate either struct since they are not my code.
I feel like I'm missing something easy here...Is there an XML attribute that I can apply to the fields?
EDIT
I've added answer using a couple surrogate properties. I'm not happy with that particular implementation since it leaves public properties hanging out.
I've also considered DataContractSerialization but I'm hesitant to take that next step quite yet. Anyone else have something they can suggest?
EDIT 2
There may have been some confusion in my wording. I can modify and decorate MyClass, WSize and DSize. However, perhaps obviously, I cannot modify System.Windows.Size or System.Drawing.Size.
You can do it by proxy with custom XML serialization, I created this fully working example, although there is a lot of error checking to be done its a place to start.
public class MyClass
{
public System.Windows.Size WSize = new System.Windows.Size();
public System.Drawing.Size DSize = new System.Drawing.Size();
}
public class MyClassProxy : MyClass, IXmlSerializable
{
public new System.Windows.Size WSize { get { return base.WSize; } set { base.WSize = value; } }
public new System.Drawing.Size DSize { get { return base.DSize; } set { base.DSize = value; } }
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(System.Xml.XmlReader reader)
{
reader.MoveToContent();
reader.ReadStartElement();
string wheight = reader["height"];
string wwidth = reader["width"];
int w, h;
w = int.Parse(wwidth);
h = int.Parse(wheight);
WSize = new Size(w, h);
reader.ReadStartElement();
string dheight = reader["height"];
string dwidth = reader["width"];
w = int.Parse(dwidth);
h = int.Parse(dheight);
DSize = new System.Drawing.Size(w, h);
}
public void WriteXml(System.Xml.XmlWriter writer)
{
writer.WriteStartElement("MyClassProxy");
writer.WriteStartElement("WSize");
writer.WriteAttributeString("height", WSize.Height.ToString());
writer.WriteAttributeString("width", WSize.Width.ToString());
writer.WriteEndElement();
writer.WriteStartElement("DSize");
writer.WriteAttributeString("height", DSize.Height.ToString());
writer.WriteAttributeString("width", DSize.Width.ToString());
writer.WriteEndElement();
writer.WriteEndElement();
}
}
class Program
{
static void Main(string[] args)
{
MyClassProxy p = new MyClassProxy();
p.DSize = new System.Drawing.Size(100, 100);
p.WSize = new Size(400, 400);
string xml = "";
using (StringWriter sw = new StringWriter())
{
System.Xml.XmlWriter wr = System.Xml.XmlWriter.Create(sw);
p.WriteXml(wr);
wr.Close();
xml = sw.ToString();
}
MyClassProxy p2 = new MyClassProxy();
using (StringReader sr = new StringReader(xml))
{
System.Xml.XmlReader r = System.Xml.XmlReader.Create(sr);
p2.ReadXml(r);
}
MyClass baseClass = (MyClass)p2;
Print(baseClass);
Console.ReadKey();
}
static void Print(MyClass c)
{
Console.WriteLine(c.DSize.ToString());
Console.WriteLine(c.WSize.ToString());
}
}
Here's a possibility that I'm not terribly happy with (not very clean):
public class MyClass
{
public System.Windows.Size WSize = new System.Windows.Size();
[XmlIgnore]
public System.Drawing.Size DSize = new Size();
public int DSizeWidthForSerialization
{
get
{
return DSize.Width;
}
set
{
DSize.Width = value;
}
}
public int DSizeHeightForSerialization
{
get
{
return DSize.Height;
}
set
{
DSize.Height = value;
}
}
}
I ended up creating a new class to house System.Drawing.Size. Within that new class I created implicit operators and handled some of the constructors. This allowed me to serialize and not have to change any existing code:
public class MyClass
{
public System.Windows.Size WSize = new System.Windows.Size();
public MyDrawingSize DSize = new System.Drawing.Size();
public class MyDrawingSize
{
public int Height, Width;
public MyDrawingSize() { } //Needed for deserialization
public MyDrawingSize(int width, int height)
{
Width = width;
Height = height;
}
public static implicit operator System.Drawing.Size(MyDrawingSize size)
{
return new System.Drawing.Size(size.Width, size.Height);
}
public static implicit operator MyDrawingSize(System.Drawing.Size size)
{
return new MyDrawingSize() { Width = size.Width, Height = size.Height };
}
}
}

WCF client produces error I don't know

I am working on an assignment and I am getting this error which I don't understand. I am writing a WCF client for a working service. Can anyone help me out here?
This line is throwing the error:
MyComplex sumcplx = proxy.complex_sum(one,two);
Error I get
Error: The best overloaded method match for 'NETProxyWCFClient.ProxyTypes.CalculatorClient.complex_sum(NETProxyWCFClient.ProxyTpes.MyComplex,NETProxyWCFClient.ProxyTpes.MyComplex)' has some invalid arguments
Code to my program
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Runtime.Serialization;
using System.ServiceModel.Description;
namespace NETProxyWCFClient
{
[DataContract]
public class MyComplex
{
int real;
[DataMember]
public int Real
{
get { return real; }
set { real = value; }
}
[DataMember]
int im;
public int Im
{
get { return im; }
set { im = value; }
}
}
[ServiceContract]
interface ICalculator
{
[OperationContract]
int mult(int a, int b);
[OperationContract]
List<int> fib(int n);
[OperationContract]
MyComplex complex_sum(MyComplex a, MyComplex b);
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter in 2 numbers");
string read = Console.ReadLine();
string[] numbers = read.Split(' ');
int m = int.Parse(numbers[0]);
int n = int.Parse(numbers[1]);
ProxyTypes.CalculatorClient proxy = new ProxyTypes.CalculatorClient();
//Multiplcation
int sum = proxy.mult(m, n);
Console.WriteLine(sum.ToString());
//Mycomplex
MyComplex one = new MyComplex();
one.Im = m;
one.Real = n;
MyComplex two = new MyComplex();
two.Im = n;
two.Real = m;
MyComplex sumcplx = proxy.complex_sum(one,two);
Console.WriteLine(sumcplx.Im + " , " + sumcplx.Real);
//fib one
int[] listM = proxy.fib(m);
foreach (int listItem in listM)
{
Console.Write(listItem.ToString() + " ");
}
Console.WriteLine("");
//fib 2
int[] listN = proxy.fib(n);
foreach (int listItem in listN)
{
Console.Write(listItem.ToString() + " ");
}
Console.ReadLine();
}
}
}
If you have Added a service reference to your test program, there is a proxt class that is generated for you, so if you have ICalculator defined explicity (code you wrote) remove it. it is already in your project, under the NETProxyWCFClient.ProxyTpes.MyComplex,NETProxyWCFClient.ProxyTpes namespace.

Mono SIMD worsening performance?

Benchmark Code:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Mono.Simd;
using MathNet.Numerics.LinearAlgebra.Single;
namespace XXX {
public static class TimeSpanExtensions {
public static double TotalNanoseconds(this TimeSpan timeSpan) {
return timeSpan.TotalMilliseconds * 1000000.0;
}
}
public sealed class SimdBenchmark : Benchmark {
Vector4f a = new Vector4f(1.0f, 2.0f, 3.0f, 4.0f);
Vector4f b = new Vector4f(1.0f, 2.0f, 3.0f, 4.0f);
Vector4f c;
public override void Do() {
c = a + b;
}
}
public sealed class MathNetBenchmark : Benchmark {
DenseVector a = new DenseVector(new float[]{1.0f,2.0f,3.0f,4.0f});
DenseVector b = new DenseVector(new float[]{1.0f,2.0f,3.0f,4.0f});
DenseVector c;
public override void Do() {
c = a + b;
}
}
public sealed class DefaultBenchmark : Benchmark {
Vector4 a = new Vector4(1.0f, 2.0f, 3.0f, 4.0f);
Vector4 b = new Vector4(1.0f, 2.0f, 3.0f, 4.0f);
Vector4 c;
public override void Do() {
c = a + b;
}
}
public sealed class SimpleBenchmark : Benchmark {
float a = 1.0f;
float b = 2.0f;
float c;
public override void Do() {
c = a + b;
}
}
public sealed class DelegateBenchmark : Benchmark {
private readonly Action _action;
public DelegateBenchmark(Action action) {
_action = action;
}
public override void Do() {
_action();
}
}
public abstract class Benchmark : IEnumerable<TimeSpan> {
public IEnumerator<TimeSpan> GetEnumerator() {
Do(); // Warm-up!
GC.Collect(); // Collect garbage.
GC.WaitForPendingFinalizers(); // Wait until finalizers finish.
var stopwatch = new Stopwatch();
while (true) {
stopwatch.Reset();
stopwatch.Start();
Do();
stopwatch.Stop();
yield return stopwatch.Elapsed;
}
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
public abstract void Do();
}
public struct Vector4 {
float x;
float y;
float z;
float w;
public Vector4(float x, float y, float z, float w) {
this.x = x;
this.y = y;
this.z = z;
this.w = w;
}
public static Vector4 operator +(Vector4 v1, Vector4 v2) {
return new Vector4(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z, v1.w + v2.w);
}
}
class MainClass {
public static void Main(string[] args) {
var avgNS1 = new SimdBenchmark().Take(1000).Average(timeSpan => timeSpan.TotalNanoseconds());
var avgNS2 = new SimpleBenchmark().Take(1000).Average(timeSpan => timeSpan.TotalNanoseconds());
var avgNS3 = new DefaultBenchmark().Take(1000).Average(timeSpan => timeSpan.TotalNanoseconds());
var avgNS4 = new MathNetBenchmark().Take(1000).Average(timeSpan => timeSpan.TotalNanoseconds());
Console.WriteLine(avgNS1 + " ns");
Console.WriteLine(avgNS2 + " ns");
Console.WriteLine(avgNS3 + " ns");
Console.WriteLine(avgNS4 + " ns");
}
}
}
Environment Setup:
Windows 7 / Mono 2.10.8 / MonoDevelop 2.8.5
MonoDevelop Setup:
Tools > Options > .NET Runtimes > Mono 2.10.8 (Default)
Project > Options > Build > General > Target framework > Mono / .NET
4.0
Project > Options > Build > Compiler > General Options > Enable optimizations
Project > Options > Build > Compiler > General Options > Platform target > x86
Project > Options > Run > General > Parameters > -O=simd
Results:
94.4 ns
29.7 ns
49.9 ns
231595.2 ns
I would suspect your benchmark infrastructure first.
A couple of points might be:
You are using a `Stopwatch` to time single operations - it doesn't have the resolution
Your timings include a virtual function call
Your sample size ( 1000 ) is too small
These are my results:
1608.8 ns
1554.9 ns
1582.5 ns
(without MathNET, although it is not important here). Os is Ubuntu 10.10 (32bit), Mono 2.10.7. At this moment you may considering making a bug report targeting Windows Mono version. But:
I think this is not the right way to benchmarking SIMD operations because of the benchmark's mechanisms overhead.
For example look on this primitive test based on your Vector4 class.
const int count = 100000;
var simdVector = new Vector4f(1, 2, 3, 4);
var simdResult = simdVector;
var sw = Stopwatch.StartNew();
for(var i = 0; i < count; i++)
{
simdResult += simdVector;
}
sw.Stop();
Console.WriteLine("SIMD result: {0} {1}", sw.Elapsed, simdResult);
sw = Stopwatch.StartNew();
var usualVector = new Vector4(1, 2, 3, 4);
var usualResult = usualVector;
for(var i = 0; i < count; i++)
{
usualResult += usualVector;
}
sw.Stop();
Console.WriteLine("Usual result: {0} {1}", sw.Elapsed, usualResult);
On my machine results are:
SIMD result: 00:00:00.0005802 <100001, 200002, 300003, 400004>
Usual result: 00:00:00.0029598 <100001, 200002, 300003, 400004>
So something definitely different than your tests. So you may think that SIMD operations are that factor faster - but benchmarking is not that easy. There are many reasons for the upper loop being faster in this configuration. These reasons can be discussed on another occasion.
Nevertheless it is sure that SIMD are faster than couple of adds in a row. What you should check for is whether they are really emitted.
On Linux, one can check generated assembly (in the meaning of target processor's assembly, not the mono assembly ;)) using mono -v -v. Nevertheless I am not sure if it works on usual Windows system as it is probably using disas from GCC (you may have more luck using cygwin). By reading such assembly you can check whether SIMD operations are really emitted.
For example, by examining assembly generated for the above pasted program one can find that it uses addps instruction in its SIMD loop which is what we are looking for here.
Oh, and for the completeness here is output with SIMD disabled:
$ mono --optimize=-simd SimdTest.exe
SIMD result: 00:00:00.0027111 <100001, 200002, 300003, 400004>
Usual result: 00:00:00.0026127 <100001, 200002, 300003, 400004>
which is not so important as the generated assembly, containing no SIMD operations.
Hope this was helpful.
Well, I've managed to modify my benchmark code to make it more robust and completely unbiased. In other words:
First, as we discussed with Nicholas - measuring single operation might give distorted results. Moreover, as the frequency of Stopwatch is 10 million - it means that ticks occur every 100 ns. So considering this fact, previous results look rather bizarre. Therefore, in order to mitigate this issue, I decided to test 1000 operations rather than 1 at time.
Second, I'm not completely sure, but I guess that previous benchmark implementation was subjected to intensive caching, since on every iteration sums were computed between the same vectors (their components never changed). The only straightforward solution I see is to simply rebuild vectors with random components before every test.
The respective benchmark implementation is:
public static class TimeSpanExtensions {
public static double TotalNanoseconds(this TimeSpan timeSpan) {
return timeSpan.TotalMilliseconds * 1000000.0;
}
}
public static class RandomExtensions {
public static float NextFloat(this Random random) {
return (float)random.NextDouble();
}
public static float NextFloat(this Random random, float min, float max) {
return random.NextFloat() * (max - min) + min;
}
}
public sealed class SimdBenchmark : Benchmark {
Vector4f[] a = new Vector4f[1000];
Vector4f[] b = new Vector4f[1000];
Vector4f[] c = new Vector4f[1000];
public override void Begin() {
Random r = new Random();
for (int i = 0; i < 1000; ++i) {
a[i] = new Vector4f(r.NextFloat(), r.NextFloat(), r.NextFloat(), r.NextFloat());
b[i] = new Vector4f(r.NextFloat(), r.NextFloat(), r.NextFloat(), r.NextFloat());
}
}
public override void Do() {
for (int i = 0; i < 1000; ++i)
c[i] = a[i] + b[i];
}
public override void End() {
}
}
public sealed class MathNetBenchmark : Benchmark {
DenseVector[] a = new DenseVector[1000];
DenseVector[] b = new DenseVector[1000];
DenseVector[] c = new DenseVector[1000];
public override void Begin() {
Random r = new Random();
for (int i = 0; i < 1000; ++i) {
a[i] = new DenseVector(new float[]{r.NextFloat(), r.NextFloat(), r.NextFloat(), r.NextFloat()});
b[i] = new DenseVector(new float[]{r.NextFloat(), r.NextFloat(), r.NextFloat(), r.NextFloat()});
}
}
public override void Do() {
for (int i = 0; i < 1000; ++i)
c[i] = a[i] + b[i];
}
public override void End() {
}
}
public sealed class DefaultBenchmark : Benchmark {
Vector4[] a = new Vector4[1000];
Vector4[] b = new Vector4[1000];
Vector4[] c = new Vector4[1000];
public override void Begin() {
Random r = new Random();
for (int i = 0; i < 1000; ++i) {
a[i] = new Vector4(r.NextFloat(), r.NextFloat(), r.NextFloat(), r.NextFloat());
b[i] = new Vector4(r.NextFloat(), r.NextFloat(), r.NextFloat(), r.NextFloat());
}
}
public override void Do() {
for (int i = 0; i < 1000; ++i)
c[i] = a[i] + b[i];
}
public override void End() {
}
}
public sealed class SimpleBenchmark : Benchmark {
float[] a = new float[1000];
float[] b = new float[1000];
float[] c = new float[1000];
public override void Begin() {
Random r = new Random();
for (int i = 0; i < 1000; ++i) {
a[i] = r.NextFloat();
b[i] = r.NextFloat();
}
}
public override void Do() {
for (int i = 0; i < 1000; ++i)
c[i] = a[i] + b[i];
}
public override void End() {
}
}
public sealed class DelegateBenchmark : Benchmark {
private readonly Action _action;
public DelegateBenchmark(Action action) {
_action = action;
}
public override void Begin() {
}
public override void Do() {
_action();
}
public override void End() {
}
}
public abstract class Benchmark : IEnumerable<TimeSpan> {
public IEnumerator<TimeSpan> GetEnumerator() {
Begin();
Do(); // Warm-up!
End();
var stopwatch = new Stopwatch();
while (true) {
Begin();
GC.Collect(); // Collect garbage.
GC.WaitForPendingFinalizers(); // Wait until finalizers finish.
stopwatch.Reset();
stopwatch.Start();
Do();
stopwatch.Stop();
End();
yield return stopwatch.Elapsed;
}
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
public abstract void Begin();
public abstract void Do();
public abstract void End();
}
public struct Vector4 {
float x;
float y;
float z;
float w;
public Vector4(float x, float y, float z, float w) {
this.x = x;
this.y = y;
this.z = z;
this.w = w;
}
public static Vector4 operator +(Vector4 v1, Vector4 v2) {
return new Vector4(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z, v1.w + v2.w);
}
}
class MainClass {
public static void Main(string[] args) {
var avgNS1 = new SimdBenchmark().Take(1000).Average(timeSpan => timeSpan.TotalNanoseconds());
var avgNS2 = new SimpleBenchmark().Take(1000).Average(timeSpan => timeSpan.TotalNanoseconds());
var avgNS3 = new DefaultBenchmark().Take(1000).Average(timeSpan => timeSpan.TotalNanoseconds());
var avgNS4 = new MathNetBenchmark().Take(1000).Average(timeSpan => timeSpan.TotalNanoseconds());
Console.WriteLine(avgNS1 + " ns");
Console.WriteLine(avgNS2 + " ns");
Console.WriteLine(avgNS3 + " ns");
Console.WriteLine(avgNS4 + " ns");
}
}
Results:
3203.9 ns
2677.4 ns
20138.4 ns
597581060.7 ns
I think it confirms that SIMD is on air, because SimdBenchmark is getting close to SimpleBenchmark (as intended by SIMD technology) and is much better than DefaultBenchmark (again as implied by SIMD technology).
Moreover, the results seems consistent with konrad.kruczynski, because the ratio between SimdBenchmark (3203.9) and DefaultBenchmark (20138.4) is about 6 and the ratio between simdVector (5802) and usualVector (29598) is also about 6.
Anyway 2 questions still remain:
Why playing with "-O=simd" / "-O=-simd" has no effect. Is it deprecated? Is SIMD automatically engaged?
How could Stopwatch with 100 ns ticks give previous results (94.4, 29.7, 49.9), which are obviously lower than 100 ns?

Categories