Performance-tuning a simple 2D Table construct

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
1
down vote

favorite












I've recently been playing with some performance tuning over a seemingly simple construction where I build a 2D array of Sin[x*y] for x, y∈Interval[0, 2π, 0, 2π].



I think it's also a good example of how vastly different results one can get depending on how efficiently the operation is performed.



Here's the operation in the simplest/least efficient way I could think up:



Table[N@Sin[x*y], 
x, 0, 2π, π/250,
y, 0, 2π, π/250
]; // RepeatedTiming // First

2.01


Now, how can we speed this up? (or slow it down in non-intuitive ways)



For reference, the best I managed to get was 0.0011 but all answers are good answers, especially if they provide analysis of how they speed up/slow down the problem.



Also feel free to cut down on the number of points 250 was simply most evocative.










share|improve this question



























    up vote
    1
    down vote

    favorite












    I've recently been playing with some performance tuning over a seemingly simple construction where I build a 2D array of Sin[x*y] for x, y∈Interval[0, 2π, 0, 2π].



    I think it's also a good example of how vastly different results one can get depending on how efficiently the operation is performed.



    Here's the operation in the simplest/least efficient way I could think up:



    Table[N@Sin[x*y], 
    x, 0, 2π, π/250,
    y, 0, 2π, π/250
    ]; // RepeatedTiming // First

    2.01


    Now, how can we speed this up? (or slow it down in non-intuitive ways)



    For reference, the best I managed to get was 0.0011 but all answers are good answers, especially if they provide analysis of how they speed up/slow down the problem.



    Also feel free to cut down on the number of points 250 was simply most evocative.










    share|improve this question

























      up vote
      1
      down vote

      favorite









      up vote
      1
      down vote

      favorite











      I've recently been playing with some performance tuning over a seemingly simple construction where I build a 2D array of Sin[x*y] for x, y∈Interval[0, 2π, 0, 2π].



      I think it's also a good example of how vastly different results one can get depending on how efficiently the operation is performed.



      Here's the operation in the simplest/least efficient way I could think up:



      Table[N@Sin[x*y], 
      x, 0, 2π, π/250,
      y, 0, 2π, π/250
      ]; // RepeatedTiming // First

      2.01


      Now, how can we speed this up? (or slow it down in non-intuitive ways)



      For reference, the best I managed to get was 0.0011 but all answers are good answers, especially if they provide analysis of how they speed up/slow down the problem.



      Also feel free to cut down on the number of points 250 was simply most evocative.










      share|improve this question















      I've recently been playing with some performance tuning over a seemingly simple construction where I build a 2D array of Sin[x*y] for x, y∈Interval[0, 2π, 0, 2π].



      I think it's also a good example of how vastly different results one can get depending on how efficiently the operation is performed.



      Here's the operation in the simplest/least efficient way I could think up:



      Table[N@Sin[x*y], 
      x, 0, 2π, π/250,
      y, 0, 2π, π/250
      ]; // RepeatedTiming // First

      2.01


      Now, how can we speed this up? (or slow it down in non-intuitive ways)



      For reference, the best I managed to get was 0.0011 but all answers are good answers, especially if they provide analysis of how they speed up/slow down the problem.



      Also feel free to cut down on the number of points 250 was simply most evocative.







      performance-tuning






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited 39 mins ago

























      asked 45 mins ago









      b3m2a1

      25.2k254148




      25.2k254148




















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          3
          down vote













          Use packed arrays, and vector operations. Here are 2 possibilities:



          Table[N@Sin[x*y],x,0,2π,π/12,y,0,2π,π/12]; //RepeatedTiming//First

          With[pa=Developer`ToPackedArray @ N @ Range[0,2π,π/12],
          Sin @ Outer[Times, pa, pa]
          ]; //RepeatedTiming//First

          With[pa=Developer`ToPackedArray @ N @ Range[0,2π,π/12],
          Sin @ KroneckerProduct[pa, pa]
          ]; //RepeatedTiming//First



          0.0025



          0.0000322



          0.0000314




          Update



          It seems that converting to a packed array takes the most time, so here is a version that avoids packing:



          With[pa = Range[0, 24] N[Pi/12],
          Sin @ KroneckerProduct[pa, pa]
          ]; //RepeatedTiming //First



          8.3*10^-6







          share|improve this answer






















          • I like the use of KroneckerProduct. I hadn't thought to use that.
            – b3m2a1
            37 mins ago






          • 1




            Range[0., 2 [Pi], 2 [Pi]/ 500] or Subdivide[0., 2 Pi, 500] are even faster because they generate packed arrays right from the start.
            – Henrik Schumacher
            22 mins ago










          • @HenrikSchumacher oh good thinking with Subdivide. My brain just immediately jumps to Range but there's really no reason for that. It also looks like Subdivide blows Range out of the water here...
            – b3m2a1
            20 mins ago











          • @HenrikSchumacher another odd subtle point... Range[0., 2. [Pi], [Pi]/250] is much slower than Range[0., 2. [Pi], [Pi]/250.]
            – b3m2a1
            16 mins ago

















          up vote
          2
          down vote













          With[r = Range[0., 2Pi, Pi/12.] , Sin @ Outer[Times, r, r]];// RepeatedTiming// First



          0.000014







          share|improve this answer




















            Your Answer





            StackExchange.ifUsing("editor", function ()
            return StackExchange.using("mathjaxEditing", function ()
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["$", "$"], ["\\(","\\)"]]);
            );
            );
            , "mathjax-editing");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "387"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f185048%2fperformance-tuning-a-simple-2d-table-construct%23new-answer', 'question_page');

            );

            Post as a guest






























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            3
            down vote













            Use packed arrays, and vector operations. Here are 2 possibilities:



            Table[N@Sin[x*y],x,0,2π,π/12,y,0,2π,π/12]; //RepeatedTiming//First

            With[pa=Developer`ToPackedArray @ N @ Range[0,2π,π/12],
            Sin @ Outer[Times, pa, pa]
            ]; //RepeatedTiming//First

            With[pa=Developer`ToPackedArray @ N @ Range[0,2π,π/12],
            Sin @ KroneckerProduct[pa, pa]
            ]; //RepeatedTiming//First



            0.0025



            0.0000322



            0.0000314




            Update



            It seems that converting to a packed array takes the most time, so here is a version that avoids packing:



            With[pa = Range[0, 24] N[Pi/12],
            Sin @ KroneckerProduct[pa, pa]
            ]; //RepeatedTiming //First



            8.3*10^-6







            share|improve this answer






















            • I like the use of KroneckerProduct. I hadn't thought to use that.
              – b3m2a1
              37 mins ago






            • 1




              Range[0., 2 [Pi], 2 [Pi]/ 500] or Subdivide[0., 2 Pi, 500] are even faster because they generate packed arrays right from the start.
              – Henrik Schumacher
              22 mins ago










            • @HenrikSchumacher oh good thinking with Subdivide. My brain just immediately jumps to Range but there's really no reason for that. It also looks like Subdivide blows Range out of the water here...
              – b3m2a1
              20 mins ago











            • @HenrikSchumacher another odd subtle point... Range[0., 2. [Pi], [Pi]/250] is much slower than Range[0., 2. [Pi], [Pi]/250.]
              – b3m2a1
              16 mins ago














            up vote
            3
            down vote













            Use packed arrays, and vector operations. Here are 2 possibilities:



            Table[N@Sin[x*y],x,0,2π,π/12,y,0,2π,π/12]; //RepeatedTiming//First

            With[pa=Developer`ToPackedArray @ N @ Range[0,2π,π/12],
            Sin @ Outer[Times, pa, pa]
            ]; //RepeatedTiming//First

            With[pa=Developer`ToPackedArray @ N @ Range[0,2π,π/12],
            Sin @ KroneckerProduct[pa, pa]
            ]; //RepeatedTiming//First



            0.0025



            0.0000322



            0.0000314




            Update



            It seems that converting to a packed array takes the most time, so here is a version that avoids packing:



            With[pa = Range[0, 24] N[Pi/12],
            Sin @ KroneckerProduct[pa, pa]
            ]; //RepeatedTiming //First



            8.3*10^-6







            share|improve this answer






















            • I like the use of KroneckerProduct. I hadn't thought to use that.
              – b3m2a1
              37 mins ago






            • 1




              Range[0., 2 [Pi], 2 [Pi]/ 500] or Subdivide[0., 2 Pi, 500] are even faster because they generate packed arrays right from the start.
              – Henrik Schumacher
              22 mins ago










            • @HenrikSchumacher oh good thinking with Subdivide. My brain just immediately jumps to Range but there's really no reason for that. It also looks like Subdivide blows Range out of the water here...
              – b3m2a1
              20 mins ago











            • @HenrikSchumacher another odd subtle point... Range[0., 2. [Pi], [Pi]/250] is much slower than Range[0., 2. [Pi], [Pi]/250.]
              – b3m2a1
              16 mins ago












            up vote
            3
            down vote










            up vote
            3
            down vote









            Use packed arrays, and vector operations. Here are 2 possibilities:



            Table[N@Sin[x*y],x,0,2π,π/12,y,0,2π,π/12]; //RepeatedTiming//First

            With[pa=Developer`ToPackedArray @ N @ Range[0,2π,π/12],
            Sin @ Outer[Times, pa, pa]
            ]; //RepeatedTiming//First

            With[pa=Developer`ToPackedArray @ N @ Range[0,2π,π/12],
            Sin @ KroneckerProduct[pa, pa]
            ]; //RepeatedTiming//First



            0.0025



            0.0000322



            0.0000314




            Update



            It seems that converting to a packed array takes the most time, so here is a version that avoids packing:



            With[pa = Range[0, 24] N[Pi/12],
            Sin @ KroneckerProduct[pa, pa]
            ]; //RepeatedTiming //First



            8.3*10^-6







            share|improve this answer














            Use packed arrays, and vector operations. Here are 2 possibilities:



            Table[N@Sin[x*y],x,0,2π,π/12,y,0,2π,π/12]; //RepeatedTiming//First

            With[pa=Developer`ToPackedArray @ N @ Range[0,2π,π/12],
            Sin @ Outer[Times, pa, pa]
            ]; //RepeatedTiming//First

            With[pa=Developer`ToPackedArray @ N @ Range[0,2π,π/12],
            Sin @ KroneckerProduct[pa, pa]
            ]; //RepeatedTiming//First



            0.0025



            0.0000322



            0.0000314




            Update



            It seems that converting to a packed array takes the most time, so here is a version that avoids packing:



            With[pa = Range[0, 24] N[Pi/12],
            Sin @ KroneckerProduct[pa, pa]
            ]; //RepeatedTiming //First



            8.3*10^-6








            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited 25 mins ago

























            answered 38 mins ago









            Carl Woll

            63.4k282163




            63.4k282163











            • I like the use of KroneckerProduct. I hadn't thought to use that.
              – b3m2a1
              37 mins ago






            • 1




              Range[0., 2 [Pi], 2 [Pi]/ 500] or Subdivide[0., 2 Pi, 500] are even faster because they generate packed arrays right from the start.
              – Henrik Schumacher
              22 mins ago










            • @HenrikSchumacher oh good thinking with Subdivide. My brain just immediately jumps to Range but there's really no reason for that. It also looks like Subdivide blows Range out of the water here...
              – b3m2a1
              20 mins ago











            • @HenrikSchumacher another odd subtle point... Range[0., 2. [Pi], [Pi]/250] is much slower than Range[0., 2. [Pi], [Pi]/250.]
              – b3m2a1
              16 mins ago
















            • I like the use of KroneckerProduct. I hadn't thought to use that.
              – b3m2a1
              37 mins ago






            • 1




              Range[0., 2 [Pi], 2 [Pi]/ 500] or Subdivide[0., 2 Pi, 500] are even faster because they generate packed arrays right from the start.
              – Henrik Schumacher
              22 mins ago










            • @HenrikSchumacher oh good thinking with Subdivide. My brain just immediately jumps to Range but there's really no reason for that. It also looks like Subdivide blows Range out of the water here...
              – b3m2a1
              20 mins ago











            • @HenrikSchumacher another odd subtle point... Range[0., 2. [Pi], [Pi]/250] is much slower than Range[0., 2. [Pi], [Pi]/250.]
              – b3m2a1
              16 mins ago















            I like the use of KroneckerProduct. I hadn't thought to use that.
            – b3m2a1
            37 mins ago




            I like the use of KroneckerProduct. I hadn't thought to use that.
            – b3m2a1
            37 mins ago




            1




            1




            Range[0., 2 [Pi], 2 [Pi]/ 500] or Subdivide[0., 2 Pi, 500] are even faster because they generate packed arrays right from the start.
            – Henrik Schumacher
            22 mins ago




            Range[0., 2 [Pi], 2 [Pi]/ 500] or Subdivide[0., 2 Pi, 500] are even faster because they generate packed arrays right from the start.
            – Henrik Schumacher
            22 mins ago












            @HenrikSchumacher oh good thinking with Subdivide. My brain just immediately jumps to Range but there's really no reason for that. It also looks like Subdivide blows Range out of the water here...
            – b3m2a1
            20 mins ago





            @HenrikSchumacher oh good thinking with Subdivide. My brain just immediately jumps to Range but there's really no reason for that. It also looks like Subdivide blows Range out of the water here...
            – b3m2a1
            20 mins ago













            @HenrikSchumacher another odd subtle point... Range[0., 2. [Pi], [Pi]/250] is much slower than Range[0., 2. [Pi], [Pi]/250.]
            – b3m2a1
            16 mins ago




            @HenrikSchumacher another odd subtle point... Range[0., 2. [Pi], [Pi]/250] is much slower than Range[0., 2. [Pi], [Pi]/250.]
            – b3m2a1
            16 mins ago










            up vote
            2
            down vote













            With[r = Range[0., 2Pi, Pi/12.] , Sin @ Outer[Times, r, r]];// RepeatedTiming// First



            0.000014







            share|improve this answer
























              up vote
              2
              down vote













              With[r = Range[0., 2Pi, Pi/12.] , Sin @ Outer[Times, r, r]];// RepeatedTiming// First



              0.000014







              share|improve this answer






















                up vote
                2
                down vote










                up vote
                2
                down vote









                With[r = Range[0., 2Pi, Pi/12.] , Sin @ Outer[Times, r, r]];// RepeatedTiming// First



                0.000014







                share|improve this answer












                With[r = Range[0., 2Pi, Pi/12.] , Sin @ Outer[Times, r, r]];// RepeatedTiming// First



                0.000014








                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered 32 mins ago









                kglr

                169k8192395




                169k8192395



























                     

                    draft saved


                    draft discarded















































                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f185048%2fperformance-tuning-a-simple-2d-table-construct%23new-answer', 'question_page');

                    );

                    Post as a guest













































































                    Popular posts from this blog

                    How to check contact read email or not when send email to Individual?

                    Displaying single band from multi-band raster using QGIS

                    How many registers does an x86_64 CPU actually have?