Vijay, Thanks for the feedback. Glad to hear it compiled fine.
Yes, I intend to dispatch to type-specific functions where possible
and then fall back to dynamic functions. It's a bit tedious to
implement, but it will yield the best performance. It's a shame that
C# can't infer the type on dynamically created generic types.
For example, these type-specific math operations for long and double
are 7x faster than the dynamic mixed version.
public A<long> mathi(A<long> x, A<long> y, Func<long, long, long> op) {
var z = new A<long>(y.Ravel.Length, y.Shape);
for(var i = 0; i < y.Ravel.Length; i++) {
//lambdas add about 3% overhead based upon tests of
100 times, for now worth it for code clarity
z.Ravel[i] = op(x.Ravel[0], y.Ravel[i]);
//z.Ravel[i] = x.Ravel[0] + y.Ravel[i];
}
return z;
}
public A<double> mathd(A<double> x, A<double> y, Func<double,
double, double> op) {
var z = new A<double>(y.Ravel.Length, y.Shape);
for(var i = 0; i < y.Ravel.Length; i++) {
z.Ravel[i] = op(x.Ravel[0], y.Ravel[i]);
}
return z;
}
//dynamic dispatch of math operations -- slowest, around 7x slower
public A<double> mathmixed(dynamic x, dynamic y, Func<dynamic,
dynamic, dynamic> op) {
var z = new A<double>(y.Ravel.Length, y.Shape);
for(var i = 0; i < y.Ravel.Length; i++) {
z.Ravel[i] = op(x.Ravel[0], y.Ravel[i]);
}
return z;
}
To demonstrate:
Sum up 10 million integers
microj "+/ ( 10000000 $ 1 2 3)" -n 10
Output: 19999999
Took: 46.5 ms
jconsole -js "exit [smoutput 1000*(10 (6!:2) '+/ ( 10000000 $ 1 2 3 )')"
36.9519
sum up floats:
microj "+/ ( 10000000 $ 1.2 2.3 3.4)" -n 10
Output: 22999998.8992955
Took: 45.5 ms
jconsole -js "exit [smoutput 1000*(10 (6!:2) '+/ ( 10000000 $ 1.2 2.3 3.4 )')"
39.2031
Let's avoid special-code next:
Add 3 to a large array of ints:
microj "$ 3 + ( 10000000 $ 1 2 3)" -n 10
Took: 96.4 ms
jconsole -js "exit [smoutput 1000*(10 (6!:2) '$ 3 + ( 10000000 $ 1 2 3 )')"
60.0216
Add 3.0 to a large array of floats (roughly the same)
microj "$ 3.0 + ( 10000000 $ 1.0 2.0 3.1)" -n 10
Took: 98.4 ms
jconsole -js "exit [smoutput 1000*(10 (6!:2) '$ 1.0 + ( 10000000 $ 1.1
2.2 3.3 )')"
58.9558
Add integer to array of floats - hits mixed math operation (38x slower!)
microj "$ 3 + ( 10000000 $ 1.0 2.0 3.1)" -n 10
Took: 3706.3 ms
J handles it fine
jconsole -js "exit [smoutput 1000*(10 (6!:2) '$ 3 + ( 10000000 $ 1.1
2.2 3.3 )')"
58.7644
We can add a new overload that takes the mixed long/double:
public A<double> mathmixed(A<long> x, A<double> y,
Func<dynamic, dynamic, dynamic> op) {
var z = new A<double>(y.Ravel.Length, y.Shape);
for(var i = 0; i < y.Ravel.Length; i++) {
z.Ravel[i] = op(x.Ravel[0], y.Ravel[i]);
}
return z;
}
And add it to the dispatch table:
if (op == "+") {
if (x.GetType() == typeof(A<long>) && y.GetType() ==
typeof(A<long>)) {
return mathi((A<long>)x,(A<long>)y, (a,b)=>a+b);
}
else if (x.GetType() == typeof(A<double>) &&
y.GetType() == typeof(A<double>)) {
return mathd((A<double>)x,(A<double>)y, (a,b)=>a+b);
}
//NEW CODE HERE
else if (x.GetType() == typeof(A<long>) && y.GetType()
== typeof(A<double>)) {
return mathmixed((A<long>)x,(A<double>)y, (a,b)=>a+b);
}
else if (x.GetType() != y.GetType()) {
return mathmixed(x,y, (a,b)=>a+b);
}
}
So this skips the dynamic version, but is still 6x slower than keeping
the types the same
microj "$ 3 + ( 10000000 $ 1.0 2.0 3.1)" -n 10
Took: 378.1 ms
Of course, now we still have the double/int mixed situation
microj "$ 3.0 + ( 10000000 $ 1 2 3)" -n 10
Took: 3142.9 ms
This can be resolved the same way, or we can add code to the dispatch
operation to cast if x is an atom and a different type to the same
type as the list, which would make sense for x<int> + y<float>but not
make sense for x<float> + y<int> where y has rank greater than 1. (In
other words, it is expensive to cast a list to a different type, but
not a scalar argument).
That dispatch code would look like this:
else if (x.Rank == 0 && x.GetType() != y.GetType() &&
x.GetType() == typeof(A<long>) && y.GetType()
== typeof(A<double>)) {
//experimental special code for 1 + (1.2 2.3 4.5)
var newx = new A<double>(1);
newx.Ravel[0] = ((A<long>)x).Ravel[0];
return mathd((A<double>)newx,(A<double>)y, (a,b)=>a+b);
}
Which gets us back to the performance of same types
microj "$ 1 + ( 10000000 $ 1.1 2.2 3.3)" -n 10
Took: 91.5 ms
On Wed, Jul 8, 2015 at 9:05 AM, Vijay Lulla <[email protected]> wrote:
> Joe,
> I could compile it just fine using the build.bat. It looks good and I
> like the idea of separate library (just like j.dll). Looking at your
> source code I was wondering if you intend to dispatch functions (just
> like J's implementation) based on the data types of arguments to the
> primitives. This is one of the superb, and well thought out, aspects
> of J that I like more every time I use J.
>
> I will try to share some code if and when I can.....I haven't
> programmed in C# for years now!! Regardless, good start, Joe.
> Thanks,
> Vijay.
>
> On Wed, Jul 8, 2015 at 3:19 AM, Mike Day <[email protected]> wrote:
>> OK, Joe
>> I got it to compile and discovered that I had a c# compiler without
>> needing to load the SharpDevelop IDE - needed to adapt build.bat
>> a bit to hard-wire the folder locations. This is in WIndows 8.1
>>
>> Anyway, microj.exe runs ok in a cmd window. It would be nice if
>> it didn't abort with i.10 (say), seeming to require an embedded
>> space.
>> The principle feature of any demo,
>> 10 30$'Hello World'
>> is fine.
>>
>> The unadorned noun a. crashed.
>>
>> This behaviour was puzzling:
>> "
>> +/ i. 10
>> 45
>> +/\ i. 10
>> MicroJ.Verb
>> "
>>
>> A line-feed with only spaces leads to
>> Unhandled Exception:....
>>
>> It would be nice if it would not crash on unhandled exceptions!
>>
>> But you probably know all this already.
>>
>> Well done, and good luck with the project!
>>
>> Thanks,
>> Mike
>>
>>
>>
>> On 07/07/2015 21:29, Joe Bogner wrote:
>>>
>>> I have a work-in-progress implementation of J in C# that I thought
>>> would be useful to share. It's actively being worked on, but it's to a
>>> point where it's useful enough to play with. I figured others may be
>>> interested in seeing it.
>>>
>>> https://github.com/joebo/microj
>>>
>>> Feedback is welcome
>>> ----------------------------------------------------------------------
>>> For information about J forums see http://www.jsoftware.com/forums.htm
>>>
>>
>>
>> ---
>> This email has been checked for viruses by Avast antivirus software.
>> https://www.avast.com/antivirus
>>
>>
>> ----------------------------------------------------------------------
>> For information about J forums see http://www.jsoftware.com/forums.htm
> ----------------------------------------------------------------------
> For information about J forums see http://www.jsoftware.com/forums.htm
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm