Skip to content

Commit

Permalink
Implemented typed versions of Reduce and Aggregate in NumCIL.Unsafe
Browse files Browse the repository at this point in the history
  • Loading branch information
kenkendk committed Apr 29, 2015
1 parent 4b77e14 commit d7d2bb2
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 12 deletions.
51 changes: 47 additions & 4 deletions bridge/NumCIL/NumCIL.Unsafe/Aggregate.tt
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".cs" #>
<#@ template language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
#region Copyright
/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
Expand Down Expand Up @@ -32,18 +35,58 @@ namespace NumCIL.Unsafe
{
internal static class Aggregate
{
<# foreach(string typename in new string[] {"SByte", "Byte", "Int16", "UInt16", "Int32", "UInt32", "Int64", "UInt64", "Single", "Double"}) { #>
<#
var opnames = new string[] {"Add", "Sub", "Mul", "Div", "Mod", "Min", "Max", "Pow", "And", "Or", "Xor"};

foreach(string opname in new string[] {"C"}.Union(opnames))
foreach(string typename in new string[] {"SByte", "Byte", "Int16", "UInt16", "Int32", "UInt32", "Int64", "UInt64", "Single", "Double", "Boolean"}) {

var nctype = typename;
if (nctype == "SByte")
nctype = "Int8";
else if (nctype == "Byte")
nctype = "UInt8";
else if (nctype == "Single")
nctype = "Float";

string structname = opname == "C" ? "C" : string.Format("NumCIL.{0}.{1}", nctype, opname);
string methodextra = opname == "C" ? "" : "_TypedImpl";
string outbyref = opname == "C" ? "ref " : "";


if (typename == "Boolean" && opname != "And" && opname != "Or" && opname != "Xor")
continue;

if ((typename == "Single" || typename == "Double") && (opname == "And" || opname == "Or" || opname == "Xor"))
continue;


#>
/// <summary>
/// Calculates the scalar result of applying the binary operation to all elements
/// </summary>
/// <typeparam name="C">The operation to perform</typeparam>
/// <param name="op">The operation to perform</param>
/// <param name="in1">The array to aggregate</param>
/// <returns>A scalar value that is the result of aggregating all elements</returns>
private static System.<#=typename#> Aggregate_Entry_<#=typename#><C>(C op, NdArray<System.<#=typename#>> in1)
private static System.<#=typename#> Aggregate_Entry_<#=typename#><#=methodextra#><C>(<#=structname#> op, NdArray<System.<#=typename#>> in1)
where C : struct, IBinaryOp<System.<#=typename#>>
{
System.<#=typename#> result;

<#
if (opname == "C")
{
#>
if (Apply.UFunc_Aggregate_Entry_Typed<System.<#=typename#>, <#=structname#>>(op, in1, out result))
return result;

#if DEBUG
Console.WriteLine("Generic Aggregate method <#=structname#> for <#=typename#>, with op = {0}, T = {1}", op.GetType(), typeof(System.<#=typename#>));
#endif
<#
}
#>
unsafe
{
using (var f1 = new Pinner(in1.DataAccessor))
Expand Down
76 changes: 75 additions & 1 deletion bridge/NumCIL/NumCIL.Unsafe/Apply.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ internal static partial class Apply
if (!_resolvedMethods.TryGetValue(key, out f))
{
var n = typeof(Apply).GetMethod("UFunc_Op_Inner_Unary_Scalar_Flush_" + typeof(Ta).Name + "_TypedImpl",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static,
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static,
null,
new Type[] {
op.GetType(),
Expand Down Expand Up @@ -254,5 +254,79 @@ internal static partial class Apply

return false;
}

/// <summary>
/// Attempts to use a typed version of the Binary call,
/// to avoid dependency on the JIT being able to inline struct methods
/// </summary>
/// <typeparam name="C">The type of operation to perform</typeparam>
/// <param name="op">The operation instance</param>
/// <param name="in1">The left-hand-side input argument</param>
/// <param name="in2">The right-hand-side input argument</param>
/// <param name="out">The output target</param>
internal static bool UFunc_Reduce_Inner_Flush_Typed<T, C>(C op, long axis, NdArray<T> in1, NdArray<T> @out)
{
System.Reflection.MethodInfo f;
var key = typeof(T).FullName + "#" + op.GetType().FullName + "#RED";
if (!_resolvedMethods.TryGetValue(key, out f))
{
var n = typeof(Reduce).GetMethod("UFunc_Reduce_Inner_Flush_" + typeof(T).Name + "_TypedImpl",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static,
null,
new Type[] {
op.GetType(),
axis.GetType(),
in1.GetType(),
@out.GetType()
}, null);

_resolvedMethods[key] = f = n == null ? null : n.MakeGenericMethod(new Type[] { op.GetType() });
}

if (f != null)
{
f.Invoke(null, new object[] { op, axis, in1, @out });
return true;
}

return false;
}

/// <summary>
/// Attempts to use a typed version of the Binary call,
/// to avoid dependency on the JIT being able to inline struct methods
/// </summary>
/// <typeparam name="C">The type of operation to perform</typeparam>
/// <param name="op">The operation instance</param>
/// <param name="in1">The left-hand-side input argument</param>
/// <param name="in2">The right-hand-side input argument</param>
/// <param name="out">The output target</param>
internal static bool UFunc_Aggregate_Entry_Typed<T, C>(C op, NdArray<T> in1, out T @out)
{
System.Reflection.MethodInfo f;
var key = typeof(T).FullName + "#" + op.GetType().FullName + "#AGR";
if (!_resolvedMethods.TryGetValue(key, out f))
{
var n = typeof(Aggregate).GetMethod("Aggregate_Entry_" + typeof(T).Name + "_TypedImpl",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static,
null,
new Type[] {
op.GetType(),
in1.GetType()
}, null);

_resolvedMethods[key] = f = n == null ? null : n.MakeGenericMethod(new Type[] { op.GetType() });
}

if (f != null)
{
@out = (T)f.Invoke(null, new object[] { op, in1 });
return true;
}
else
@out = default(T);

return false;
}
}
}
2 changes: 1 addition & 1 deletion bridge/NumCIL/NumCIL.Unsafe/ApplyBinary.tt
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ foreach(string typename in new string[] {"SByte", "Byte", "Int16", "UInt16", "In
string typename_out = typename;


if (typename == "Boolean" && opname != "And" && opname != "Or" && opname != "Xor")
if (typename == "Boolean" && opname != "And" && opname != "Or" && opname != "Xor" && opname != "C")
continue;

if ((typename == "Single" || typename == "Double") && (opname == "And" || opname == "Or" || opname == "Xor"))
Expand Down
2 changes: 1 addition & 1 deletion bridge/NumCIL/NumCIL.Unsafe/ApplyUnary.tt
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ foreach(string typename in new string[] {"SByte", "Byte", "Int16", "UInt16", "In
if (opname == "Not" && typename != "Boolean")
continue;

if (typename == "Boolean" && !(opname == "Not" || convertOps.Any(x => x == opname)))
if (typename == "Boolean" && !(opname == "Not" || opname == "C" || convertOps.Any(x => x == opname)))
continue;

if ((opname == "Abs" || opname == "Sign") && nctype.StartsWith("U"))
Expand Down
51 changes: 46 additions & 5 deletions bridge/NumCIL/NumCIL.Unsafe/Reduce.tt
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".cs" #>
<#@ template language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
#region Copyright
/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
Expand Down Expand Up @@ -33,7 +36,32 @@ namespace NumCIL.Unsafe
{
internal static class Reduce
{
<# foreach(string typename in new string[] {"SByte", "Byte", "Int16", "UInt16", "Int32", "UInt32", "Int64", "UInt64", "Single", "Double"}) { #>
<#
var opnames = new string[] {"Add", "Sub", "Mul", "Div", "Mod", "Min", "Max", "Pow", "And", "Or", "Xor"};

foreach(string opname in new string[] {"C"}.Union(opnames))
foreach(string typename in new string[] {"SByte", "Byte", "Int16", "UInt16", "Int32", "UInt32", "Int64", "UInt64", "Single", "Double", "Boolean"}) {

var nctype = typename;
if (nctype == "SByte")
nctype = "Int8";
else if (nctype == "Byte")
nctype = "UInt8";
else if (nctype == "Single")
nctype = "Float";

string structname = opname == "C" ? "C" : string.Format("NumCIL.{0}.{1}", nctype, opname);
string methodextra = opname == "C" ? "" : "_TypedImpl";
string outbyref = opname == "C" ? "ref " : "";

if (typename == "Boolean" && opname != "And" && opname != "Or" && opname != "Xor")
continue;

if ((typename == "Single" || typename == "Double") && (opname == "And" || opname == "Or" || opname == "Xor"))
continue;


#>
/// <summary>
/// Unsafe implementation of the reduce operation
/// </summary>
Expand All @@ -43,9 +71,22 @@ namespace NumCIL.Unsafe
/// <param name="axis">The axis to reduce</param>
/// <param name="out">The output target</param>
/// <returns>The output target</returns>
private static NdArray<System.<#=typename#>> UFunc_Reduce_Inner_Flush_<#=typename#><C>(C op, long axis, NdArray<System.<#=typename#>> in1, NdArray<System.<#=typename#>> @out)
private static NdArray<System.<#=typename#>> UFunc_Reduce_Inner_Flush_<#=typename#><#=methodextra#><C>(<#=structname#> op, long axis, NdArray<System.<#=typename#>> in1, NdArray<System.<#=typename#>> @out)
where C : struct, IBinaryOp<System.<#=typename#>>
{
<#
if (opname == "C")
{
#>
if (Apply.UFunc_Reduce_Inner_Flush_Typed<System.<#=typename#>, <#=structname#>>(op, axis, in1, @out))
return @out;

#if DEBUG
Console.WriteLine("Generic Reduce method <#=structname#> for <#=typename#>, with op = {0}, T = {1}", op.GetType(), typeof(System.<#=typename#>));
#endif
<#
}
#>
if (axis < 0)
axis = in1.Shape.Dimensions.LongLength - axis;

Expand Down Expand Up @@ -149,7 +190,7 @@ namespace NumCIL.Unsafe
{
//Select the new dimension
//Apply the operation
Apply.UFunc_Op_Inner_Binary_Flush_<#=typename#><C>(op, vl, in1.Subview(Range.El(j), axis), ref vl);
Apply.UFunc_Op_Inner_Binary_Flush_<#=typename#><<#=structname#>>(op, vl, in1.Subview(Range.El(j), axis), ref vl);
}
}
}
Expand Down

0 comments on commit d7d2bb2

Please sign in to comment.