OpBinary

c = op(alpha1 * a + alpha2 * b) + beta * c;

Members

Functions

backward
auto backward(Variable!(T, dim, HostStorage) gc)
Undocumented in source. Be warned that the author may not have intended to support it.
backward
auto backward(Variable!(T, dim, DeviceStorage) gc)
Undocumented in source. Be warned that the author may not have intended to support it.
backward
auto backward(Variable!(T, dim, DeviceStorage) gc)
Undocumented in source. Be warned that the author may not have intended to support it.
forward
auto forward(Variable!(T, dim, HostStorage) a, Variable!(T, dim, HostStorage) b)
Undocumented in source. Be warned that the author may not have intended to support it.
forward
auto forward(Variable!(T, dim, DeviceStorage) a, Variable!(T, dim, DeviceStorage) b)
Undocumented in source. Be warned that the author may not have intended to support it.

Manifest constants

opBinaryDict
enum opBinaryDict;
Undocumented in source.

Mixins

__anonymous
mixin FunctionCommon
Undocumented in source.

Variables

alpha1
T alpha1;
alpha2
T alpha2;
Undocumented in source.
da
Variable!(T, dim, DeviceStorage) da;
db
Variable!(T, dim, DeviceStorage) db;
Undocumented in source.
ha
Variable!(T, dim, HostStorage) ha;
hb
Variable!(T, dim, HostStorage) hb;
Undocumented in source.
shape1
uint[dim] shape1;
shape2
uint[dim] shape2;
Undocumented in source.

Mixed In Members

From mixin FunctionCommon

this(this)
this(this)
Undocumented in source.
DeviceRets
alias DeviceRets = Tuple!(Parameters!backward)
Undocumented in source.
DeviceArgs
alias DeviceArgs = Tuple!(Parameters!forward)
Undocumented in source.
__anonymous
mixin TypeChecker!(forward, backward)
Undocumented in source.
_mixin_dargs
DeviceArgs _mixin_dargs;
Undocumented in source.
HostRets
alias HostRets = Tuple!(Parameters!backward)
Undocumented in source.
HostArgs
alias HostArgs = Tuple!(Parameters!forward)
Undocumented in source.
__anonymous
mixin TypeChecker!(forward, backward)
Undocumented in source.
_mixin_hargs
HostArgs _mixin_hargs;
Undocumented in source.
applyForward
auto applyForward(Args args)

store grain.autograd.BackProp object in returned variables from forward function

applyBackward
void applyBackward(UntypedVariable[] ugradOutputs)

type-erased version of backward function used in grain.autograd.BackProp object

Examples

static foreach (op; ["+", "*"]) {
    foreach (j; [1, 2]) {
        import std.typecons : tuple;
        import numir : uniform, approxEqual;
        import mir.ndslice : slice;
        import grain.testing;

        auto a = uniform!float(3, 2).slice.variable;
        auto b = uniform!float(3, j).slice.variable;
        auto gc = uniform!float(3, 2).slice.variable;
        auto func = OpBinary!(float, 2, op)(1, 2);
        gradCheck(func, tuple(a, b), gc);

        auto c = func.forward(a, b);
        auto gab = func.backward(gc);
        version (grain_cuda) {
            auto dfunc = OpBinary!(float, 2, op)(1, 2);
            auto dc = dfunc.forward(a.to!DeviceStorage, b.to!DeviceStorage);
            assert(approxEqual(dc.to!HostStorage.sliced, c.sliced));
            auto dgab = dfunc.backward(gc.to!DeviceStorage);
            assert(approxEqual(dgab[0].to!HostStorage.sliced, gab[0].sliced));
            assert(approxEqual(dgab[1].to!HostStorage.sliced, gab[1].sliced));
        }
    }
}
foreach (i; [1, 2]) {
    foreach (j; [1, 2]) {
        import std.typecons : tuple;
        import numir : uniform;
        import mir.ndslice : slice;
        import grain.testing;

        auto a = uniform!float(i, 2).slice.variable;
        auto b = uniform!float(2, j).slice.variable;
        auto gc = uniform!float(2, 2).slice.variable;
        auto func = OpBinary!(float, 2, "*")(1, 2);
        gradCheck(func, tuple(a, b), gc);
    }
}

a and b have the same shape

import mir.ndslice;

auto plus = OpBinary!(float, 2, "+")(1.0f, 2.0f);
auto a = [[1.0f, 2.0f, 3.0f], [4.0f, 5.0f, 3.0f]].variable;
auto b = [[-1.0f, 4.0f, 0.0f], [1.0f, 2.0f, 3.0f]].variable;
auto hc = plus.forward(a, b);
assert(hc.sliced == [[-1.0f, 10.0f, 3.0f], [6.0f, 9.0f, 9.0f]]);

version (grain_cuda) {
    auto dplus = OpBinary!(float, 2, "+")(1.0f, 2.0f);
    auto dc = dplus.forward(a.to!DeviceStorage, b.to!DeviceStorage);
    assert(dc.to!HostStorage.sliced == [[-1.0f, 10.0f, 3.0f], [6.0f, 9.0f, 9.0f]]);
}

a and b have different shapes

import mir.ndslice;

auto plus = OpBinary!(float, 2, "+")(1.0f, 2.0f);
auto a = [[1.0f, 2.0f, 3.0f], [4.0f, 5.0f, 3.0f]].variable;
auto b = [[-1.0f, 4.0f, 0.0f]].variable;
auto hc = plus.forward(a, b);
assert(hc.sliced == [[-1.0f, 10.0f, 3.0f], [2.0f, 13.0f, 3.0f]]);

version (grain_cuda) {
    auto dc = plus.forward(a.to!DeviceStorage, b.to!DeviceStorage);
    assert(dc.to!HostStorage.sliced == [[-1.0f, 10.0f, 3.0f], [2.0f, 13.0f, 3.0f]]);
}

a and b have different shapes

import mir.ndslice;

auto plus = OpBinary!(float, 2, "*")(1.0f, 2.0f);
auto a = [[1.0f, 2.0f, 3.0f], [4.0f, 5.0f, 3.0f]].variable;
auto b = [[-1.0f, 4.0f, 0.0f]].variable;
auto hc = plus.forward(a, b);
assert(hc.sliced == [[1*2*-1, 2*2*4, 0], [4*2*-1, 5*2*4, 0]]);

version (grain_cuda) {
    auto dc = plus.forward(a.to!DeviceStorage, b.to!DeviceStorage);
    assert(dc.to!HostStorage.sliced ==[[1*2*-1, 2*2*4, 0], [4*2*-1, 5*2*4, 0]]);
}

Meta