Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A different method for reducing string based codegen #12

Open
paddymul opened this issue Sep 14, 2014 · 3 comments
Open

A different method for reducing string based codegen #12

paddymul opened this issue Sep 14, 2014 · 3 comments

Comments

@paddymul
Copy link

I took a look at the generated code and I added comments for the varying bits. It seems that the varying parts are quite small and the same for each set of dimensions. I don't see any parts that have combinations between dtype and shape. I think the string concatenated code could be greatly reduced, or possibly eliminated if you were willing to manually build out a set of dimensional arrays.

It looks like you sometimes define stride and shape as arrays, and sometimes as a varying number of scalars (_shape0, _shape2...)

If you always dealt with shape and stride as arrays, you could write generic code to deal with these cases.

Am I missing something here?

'use strict'
function View2dfloat32(a,b0,b1,c0,c1,d){this.data=a
                                        this._shape0=b0|0
                                        this._shape1=b1|0
                                        this._stride0=c0|0
                                        this._stride1=c1|0
                                        this.offset=d|0}
var proto=View2dfloat32.prototype;
proto.dtype='float32';
proto.dimension=2;
function VStride2dfloat32(v) {this._v=v;} 
var aproto=VStride2dfloat32.prototype;

//varying
aproto.length=2;
aproto.toJSON=function VStride2dfloat32_toJSON(){
    return [this._v._stride0,this._v._stride1];};
aproto.valueOf = aproto.toString= function VStride2dfloat32_toString(){
    return [this._v._stride0,this._v._stride1].join();};
Object.defineProperty(aproto,0,{
    get:function() { return this._v._stride0;},
    set:function(v){ return this._v._stride0=v|0;},
    enumerable:true});
Object.defineProperty(aproto,1,{
    get:function(){ return this._v._stride1;},
    set:function(v){return this._v._stride1=v|0;},
    enumerable:true});
//end varying
aproto.concat=Array.prototype.concat;
aproto.join=Array.prototype.join;
aproto.slice=Array.prototype.slice;
aproto.toString=Array.prototype.toString;
aproto.indexOf=Array.prototype.indexOf;
aproto.lastIndexOf=Array.prototype.lastIndexOf;
aproto.forEach=Array.prototype.forEach;
aproto.every=Array.prototype.every;
aproto.some=Array.prototype.some;
aproto.filter=Array.prototype.filter;
aproto.map=Array.prototype.map;
aproto.reduce=Array.prototype.reduce;
aproto.reduceRight=Array.prototype.reduceRight;

//varying
Object.defineProperty(proto,'stride',{
    get:function VStride2dfloat32_get(){
        return new VStride2dfloat32(this);},
    set: function VStride2dfloat32_set(v){
        this._stride0=v[0]|0;
        this._stride1=v[1]|0;
        return v;}});

function VShape2dfloat32(v) {this._v=v;} 
var aproto=VShape2dfloat32.prototype;
aproto.length=2;
aproto.toJSON=function VShape2dfloat32_toJSON(){
    return [this._v._shape0,this._v._shape1];};
aproto.valueOf=aproto.toString=function VShape2dfloat32_toString(){
    return [this._v._shape0,this._v._shape1].join()};

Object.defineProperty(aproto,0,{
    get:function(){return this._v._shape0;},
    set:function(v){return this._v._shape0=v|0;},
    enumerable:true});
Object.defineProperty(aproto,1,{
    get:function(){return this._v._shape1;},
    set:function(v){return this._v._shape1=v|0;},
    enumerable:true});

//end varying
aproto.concat=Array.prototype.concat;
aproto.join=Array.prototype.join;
aproto.slice=Array.prototype.slice;
aproto.toString=Array.prototype.toString;
aproto.indexOf=Array.prototype.indexOf;
aproto.lastIndexOf=Array.prototype.lastIndexOf;
aproto.forEach=Array.prototype.forEach;
aproto.every=Array.prototype.every;
aproto.some=Array.prototype.some;
aproto.filter=Array.prototype.filter;
aproto.map=Array.prototype.map;
aproto.reduce=Array.prototype.reduce;
aproto.reduceRight=Array.prototype.reduceRight;
//varying
Object.defineProperty(proto,'shape',{
    get:function VShape2dfloat32_get(){return new VShape2dfloat32(this);},
    set: function VShape2dfloat32_set(v){
        this._shape0=v[0]|0;
        this._shape1=v[1]|0;
        return v};});
Object.defineProperty(proto,'size',{
    get:function View2dfloat32_size(){
        return this._shape0*this._shape1;}});

Object.defineProperty(proto,'order', {
    get:function View2dfloat32_order(){
        return (Math.abs(this._stride0)>Math.abs(this._stride1))?[1,0]:[0,1];}});
proto.set=function View2dfloat32_set(i0,i1,v){
    return this.data[this.offset+this._stride0*i0+this._stride1*i1]=v;};
proto.get=function View2dfloat32_get(i0,i1){
    return this.data[this.offset+this._stride0*i0+this._stride1*i1];};
proto.index=function View2dfloat32_index(i0,i1){
    return this.offset+this._stride0*i0+this._stride1*i1;};
proto.hi=function View2dfloat32_hi(i0,i1){
    var arg2 = (typeof i0!=='number'||i0<0)?this._shape0:i0|0;
    var arg3 = (typeof i1!=='number'||i1<0)?this._shape1:i1|0;
    return new View2dfloat32(this.data,
                             arg1, 
                             arg2,
                             this._stride0,
                             this._stride1,
                             this.offset);};

proto.lo=function View2dfloat32_lo(i0,i1){
    var b = this.offset, d = 0, 
        a0 = this._shape0, a1 = this._shape1, 
        c0 = this._stride0, c1 = this._stride1;
    if(typeof i0==='number'&&i0>=0){
        d=i0|0;
        b+=c0*d;
        a0-=d}
    if(typeof i1==='number'&&i1>=0){
        d=i1|0;
        b+=c1*d;
        a1-=d}
    return new View2dfloat32(this.data,a0,a1,c0,c1,b)};
proto.step=function View2dfloat32_step(i0,i1){
    var a0=this._shape0,a1=this._shape1,
    b0=this._stride0,b1=this._stride1,
    c=this.offset,d=0,ceil=Math.ceil;
    if(typeof i0==='number'){
        d=i0|0;
        if(d<0){
            c+=b0*(a0-1);
            a0=ceil(-a0/d);}
        else{
            a0=ceil(a0/d);}
        b0*=d;}
    if(typeof i1==='number'){
        d=i1|0;
        if(d<0){
            c+=b1*(a1-1);
            a1=ceil(-a1/d);}
        else{
            a1=ceil(a1/d);}
        b1*=d};
    return new View2dfloat32(this.data,a0,a1,b0,b1,c);}
proto.transpose=function View2dfloat32_transpose(i0,i1){
    i0=(i0===undefined?0:i0|0);
    i1=(i1===undefined?1:i1|0);
    var a=this.shape,b=this.stride;
    return new View2dfloat32(this.data,a[i0],a[i1],b[i0],b[i1],this.offset);};
proto.pick=function View2dfloat32_pick(i0,i1){
    var a=[],b=[],c=this.offset;
    if(typeof i0==='number'&&i0>=0){
        c=(c+this._stride0*i0)|0}
    else{
        a.push(this._shape0);b.push(this._stride0);}

    if(typeof i1==='number'&&i1>=0){
        c=(c+this._stride1*i1)|0;}
    else{
        a.push(this._shape1);
        b.push(this._stride1);}
    var ctor=CTOR_LIST[a.length+1];
    return ctor(this.data,a,b,c);};

//end varying
return function construct_View2dfloat32(data,shape,stride,offset){
    return new View2dfloat32(data,shape[0],shape[1],stride[0],stride[1],offset);};
@mikolalysenko
Copy link
Member

There is also the special case that get/set work differently for custom data types. This is used in things like ndarray-hash to implement sparse data types.

The other issue with using arrays for shape and stride is that it slows down array accesses. You could do everything at runtime, but the whole point of using code generation is for performance.

I might add a dynamic version of ndarray for supporting systems with CSP that block Function/eval, but this would also require figuring out a better solution for cwise.

@xieyuheng
Copy link

what is "cwise"?

@rreusser
Copy link
Member

@xieyuheng It's a package for component-wise operations on ndarrays: https://www.npmjs.com/package/cwise. It accepts operations as a function but parses and rewrites them as flat, cache-efficient loops.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants