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

[cpp] Array<Array<Float>> is Dynamic ? #4549

Closed
ncannasse opened this issue Sep 15, 2015 · 19 comments
Closed

[cpp] Array<Array<Float>> is Dynamic ? #4549

ncannasse opened this issue Sep 15, 2015 · 19 comments
Assignees
Labels
platform-cpp Everything related to CPP / C++
Milestone

Comments

@ncannasse
Copy link
Member

Any reason why using Array<Array<Float> compiles to Array<::Dynamic> ? That reduces a lot the performances when using multi-dimensional arrays.

@hughsando
Copy link
Member

Every different type of array uses about 20k of exe size, so I use Array for all objects.
When the element is used, it is "StaticCast" (which should be free) to the correct type so there should be no performance loss.
If you are using non-generic template functions or "Array" explicitly you can end up actual Dynamic access, but this is a different story.

@ncannasse
Copy link
Member Author

Ok so there must be another problem, because the following code is wayyyy slower in hxcpp than in haxe/JS:

class Bench
{
  static public function main():Void 
  {
    //read input
    var array = new Array<Array<Float>>();

    array = [
                [3],
                [7,4],
                [2,4,6],
                [8,5,9,3]
                            ];


    var sum = 0.0;
    for ( i in 0...10000000 ){
        sum += Solve(array);
    }
    trace(sum);
  }

  static private function Solve(t:Array<Array<Float>>):Float
  {
    for ( idxLine in (1...t.length) ){
        for ( idxCol in (0...t[idxLine].length) ){
            if ( idxCol == 0){
                t[idxLine][idxCol] += t[idxLine-1][0];
            } else if (idxCol == t[idxLine].length-1){
                t[idxLine][idxCol] += t[idxLine-1][idxCol-1];
            } else {
                t[idxLine][idxCol] += Math.max(t[idxLine-1][idxCol-1], t[idxLine-1][idxCol]);
            }
        }
    } 

    var maxi = -1.0;
    for (elem in t[t.length-1]){
        maxi = Math.max(maxi, elem);
    }
    return maxi;
  }
}

@ncannasse ncannasse reopened this Sep 16, 2015
@hughsando
Copy link
Member

Yes I see - it is actually doing a dynamic_cast in this case. The reason for this is that I fundamentally can't trust the type of array data, eg:

static function make2DArray<T>(inVal:T) return [[inVal]];

public static function main()
{
   var a = make2DArray(1.2);
   trace(a[0][0]);
}

Here, haxe says that make2DArray is returning an Array<Array<Float>> but actually it is returning a Array<Array< TypeParam=Float >>. If I knew the difference, then I wouldn't have to be conservative.
I have done some investigations along these lines, but it is all part of the same "Funky array typing from generics" issue.

@andyli andyli added the platform-cpp Everything related to CPP / C++ label Sep 30, 2015
@Simn Simn modified the milestone: 3.3.0-rc1 Feb 23, 2016
@Simn
Copy link
Member

Simn commented Mar 18, 2016

Is this still an issue? Running the benchmark I get comparable results between JS and C++.

@Simn
Copy link
Member

Simn commented Mar 19, 2016

Target Time Notes
cpp 0.851547822013147s no difference with -D cppast
js 0.880000114440918s
java 1s Timer.measure inaccurate?
hlc 1.530998229980469s
cs erase_generics 3.95957350730896s hmm...
cs 11.7414352893829s ouch
cppia 22.3074205864312s
swf 33.684s
neko 38.2049999237061s
as3 41.191s
lua 101s
interp 229.78099989891052s
php 291.32040405273s
hl interp 292s
python ? Timer.measure broken?

Personal conclusion:

  • Java is surprisingly fast.
  • C# is surprisingly slow.
  • The HL interpreter being slow is not surprising given the opcode format. Being beaten by PHP still stings.
  • I don't know how to feel about --interp.
  • HLC makes a good entry given its early stage.

@delahee
Copy link
Contributor

delahee commented Mar 19, 2016

2c...Be careful c# startup is slow because of the initial JIT phase but
after startup, speed should be slightly comparable to java...OR there is a
big problem...OR Java has made big improvements...Whatever :)

2016-03-19 11:18 GMT+01:00 Simon Krajewski notifications@github.com:

Target Time Notes
cpp 0.851547822013147s no difference with -D cppast
js 0.880000114440918s
java 1s Timer.measure inaccurate?
hlc 1.530998229980469s
cs erase_generics 3.95957350730896s hmm...
cs 11.7414352893829s ouch
cppia 22.3074205864312s
swf 33.684s
neko 38.2049999237061s
as3 41.191s
lua 101s
interp 229.78099989891052s
php 291.32040405273s
hl interp 292s
python ? Timer.measure broken?

Personal conclusion:

  • Java is surprisingly fast.
  • C# is surprisingly slow.
  • The HL interpreter being slow is not surprising given the opcode
    format. Being beaten by PHP still stings.
  • I don't know how to feel about --interp.
  • HLC makes a good entry given its early stage.


You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub
#4549 (comment)

David Elahee

@Simn
Copy link
Member

Simn commented Mar 19, 2016

This is measured within main, there should be no startup involved.

@nadako
Copy link
Member

nadako commented Mar 19, 2016

C# without -D erase-generics involves a lot of type checks (the _hx_cast thing, #4872), this is most probably the cause of the slowdown. I'll profile it with dottrace to see if that's true.

@Simn
Copy link
Member

Simn commented Mar 19, 2016

Well, even with erase-generics it seems slower than it should be.

@nadako
Copy link
Member

nadako commented Mar 19, 2016

Could you post the full benchmark code?

@Simn
Copy link
Member

Simn commented Mar 19, 2016

It's just Nicolas' code with a Timer.measure around the loop:

class Main
{
  static public function main():Void
  {
    //read input
    var array = new Array<Array<Float>>();

    array = [
                [3],
                [7,4],
                [2,4,6],
                [8,5,9,3]
                            ];

    haxe.Timer.measure(function() {
    var sum = 0.0;
    for ( i in 0...10000000 ){
        sum += Solve(array);
    }
    trace(sum);
    });
  }

  static private function Solve(t:Array<Array<Float>>):Float
  {
    for ( idxLine in (1...t.length) ){
        for ( idxCol in (0...t[idxLine].length) ){
            if ( idxCol == 0){
                t[idxLine][idxCol] += t[idxLine-1][0];
            } else if (idxCol == t[idxLine].length-1){
                t[idxLine][idxCol] += t[idxLine-1][idxCol-1];
            } else {
                t[idxLine][idxCol] += Math.max(t[idxLine-1][idxCol-1], t[idxLine-1][idxCol]);
            }
        }
    }

    var maxi = -1.0;
    for (elem in t[t.length-1]){
        maxi = Math.max(maxi, elem);
    }
    return maxi;
  }
}

@nadako
Copy link
Member

nadako commented Mar 19, 2016

I think I was right, here's a sampler output:

@nadako
Copy link
Member

nadako commented Mar 19, 2016

Arrays with their bound checking don't help as well :-/

@Simn
Copy link
Member

Simn commented Mar 19, 2016

Is that with generics erased or without?

@nadako
Copy link
Member

nadako commented Mar 19, 2016

Without

@Simn
Copy link
Member

Simn commented Mar 19, 2016

Alright then, I guess that means we can close here because it has been addressed on hxcpp and is gonna be an instance of #4872 on C#.

@Simn Simn closed this as completed Mar 19, 2016
@nadako
Copy link
Member

nadako commented Mar 19, 2016

Here's the output WITH -D erase-generics

This is about unboxing object to double...

@hughsando
Copy link
Member

These benchmarks suggest to me that maybe we should be linking in something like v8 for --interp.

@ncannasse
Copy link
Member Author

HL interp does a LOT of validation checks (basically typecheck every register you assign to) in order to check that nothing is wrongly compiled. It's not been written with performances in mind, but could eventually be modified, although it would still suffer the same additional wrapping for all values that affects neko interp.

@Simn Simn mentioned this issue Apr 4, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
platform-cpp Everything related to CPP / C++
Projects
None yet
Development

No branches or pull requests

6 participants