Armadillo does not perform swap optimization











up vote
1
down vote

favorite












How to swap Armadillo objects, e.g. arma::vecs, without swapping contents?



void f5()
{
arma::vec x(10);
arma::vec y(10);
std::cout << &x[2] << ", " << &y[2] << "n";
x.swap(y);
std::cout << &x[2] << ", " << &y[2];
}


The above code outputs



0x24fbe50, 0x24fbef0
0x24fbe50, 0x24fbef0


Thank you!










share|improve this question






















  • Can you increase the vector size and try it again? Maybe they do silly memcpy if the array size is below some threshold.
    – OZ17
    Nov 10 at 22:56










  • @OZ17 Great! Seems swap optimization happens for >= 17 doubles on my machine. I'll accept it if you want to post your comment as an answer.
    – user2961927
    Nov 11 at 0:27















up vote
1
down vote

favorite












How to swap Armadillo objects, e.g. arma::vecs, without swapping contents?



void f5()
{
arma::vec x(10);
arma::vec y(10);
std::cout << &x[2] << ", " << &y[2] << "n";
x.swap(y);
std::cout << &x[2] << ", " << &y[2];
}


The above code outputs



0x24fbe50, 0x24fbef0
0x24fbe50, 0x24fbef0


Thank you!










share|improve this question






















  • Can you increase the vector size and try it again? Maybe they do silly memcpy if the array size is below some threshold.
    – OZ17
    Nov 10 at 22:56










  • @OZ17 Great! Seems swap optimization happens for >= 17 doubles on my machine. I'll accept it if you want to post your comment as an answer.
    – user2961927
    Nov 11 at 0:27













up vote
1
down vote

favorite









up vote
1
down vote

favorite











How to swap Armadillo objects, e.g. arma::vecs, without swapping contents?



void f5()
{
arma::vec x(10);
arma::vec y(10);
std::cout << &x[2] << ", " << &y[2] << "n";
x.swap(y);
std::cout << &x[2] << ", " << &y[2];
}


The above code outputs



0x24fbe50, 0x24fbef0
0x24fbe50, 0x24fbef0


Thank you!










share|improve this question













How to swap Armadillo objects, e.g. arma::vecs, without swapping contents?



void f5()
{
arma::vec x(10);
arma::vec y(10);
std::cout << &x[2] << ", " << &y[2] << "n";
x.swap(y);
std::cout << &x[2] << ", " << &y[2];
}


The above code outputs



0x24fbe50, 0x24fbef0
0x24fbe50, 0x24fbef0


Thank you!







c++ armadillo






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 10 at 22:00









user2961927

430516




430516












  • Can you increase the vector size and try it again? Maybe they do silly memcpy if the array size is below some threshold.
    – OZ17
    Nov 10 at 22:56










  • @OZ17 Great! Seems swap optimization happens for >= 17 doubles on my machine. I'll accept it if you want to post your comment as an answer.
    – user2961927
    Nov 11 at 0:27


















  • Can you increase the vector size and try it again? Maybe they do silly memcpy if the array size is below some threshold.
    – OZ17
    Nov 10 at 22:56










  • @OZ17 Great! Seems swap optimization happens for >= 17 doubles on my machine. I'll accept it if you want to post your comment as an answer.
    – user2961927
    Nov 11 at 0:27
















Can you increase the vector size and try it again? Maybe they do silly memcpy if the array size is below some threshold.
– OZ17
Nov 10 at 22:56




Can you increase the vector size and try it again? Maybe they do silly memcpy if the array size is below some threshold.
– OZ17
Nov 10 at 22:56












@OZ17 Great! Seems swap optimization happens for >= 17 doubles on my machine. I'll accept it if you want to post your comment as an answer.
– user2961927
Nov 11 at 0:27




@OZ17 Great! Seems swap optimization happens for >= 17 doubles on my machine. I'll accept it if you want to post your comment as an answer.
– user2961927
Nov 11 at 0:27












2 Answers
2






active

oldest

votes

















up vote
0
down vote



accepted










Looks like armadillo's swap is internally a memcpy below a certain array size (according to op <=16).






share|improve this answer




























    up vote
    2
    down vote













    A small expansion of @OZ17's answer.
    Armadillo seems to store data with sizes< 16 locally mem_localand larger ones in an area pointed out by mem



    From GDB:
    > p x
    {
    <arma::Mat<double>> = {
    <arma::Base<double, arma::Mat<double> >> = {
    <arma::Base_inv_yes<arma::Mat<double> >> = {<No data fields>},
    <arma::Base_eval_Mat<double, arma::Mat<double> >> = {<No data fields>},
    <arma::Base_trans_default<arma::Mat<double> >> = {<No data fields>}, <No data fields>},
    members of arma::Mat<double>:
    n_rows = 1,
    n_cols = 10,
    n_elem = 10,
    vec_state = 2,
    mem_state = 0,
    mem = 0x7fffffffb830,
    mem_local = {0 <repeats 16 times>},
    static is_col = false,
    static is_row = false
    },
    members of arma::Row<double>:
    static is_col = false,
    static is_row = false
    }


    and a small example to visualize it:



    arma::rowvec x(10,arma::fill::ones);
    arma::rowvec y(10,arma::fill::zeros);
    std::cout << "Size=10" << std::endl;
    std::cout << "&x=" << x.memptr() << ", x[0..4]=" << x.subvec(1,5);
    std::cout << "&y=" << y.memptr() << ", y[0..4]=" << y.subvec(1,5);
    x.swap(y);
    std::cout << "x.swap(y)" << std::endl;
    std::cout << "&x=" << x.memptr() << ", x[0..4]=" << x.subvec(1,5);
    std::cout << "&y=" << y.memptr() << ", y[0..4]=" << y.subvec(1,5);

    arma::rowvec x2(17,arma::fill::ones);
    arma::rowvec y2(17,arma::fill::zeros);
    std::cout << "nSize=17" << std::endl;
    std::cout << "&x=" << x2.memptr() << ", x[0..4]=" << x2.subvec(1,5);
    std::cout << "&y=" << y2.memptr() << ", y[0..4]=" << y2.subvec(1,5);
    x2.swap(y2);
    std::cout << "x.swap(y)" << std::endl;
    std::cout << "&x=" << x2.memptr() << ", x[0..4]=" << x2.subvec(1,5);
    std::cout << "&y=" << y2.memptr() << ", y[0..4]=" << y2.subvec(1,5);


    The output from the example shows that the content is swapped in both cases but for small arrays it has swapped the local mem area and for the larger case it has swapped the mem pointer.



    Size=10
    &x=0x7fffffffb830, x[0..4]= 1.0000 1.0000 1.0000 1.0000 1.0000
    &y=0x7fffffffb8e0, y[0..4]= 0 0 0 0 0
    x.swap(y)
    &x=0x7fffffffb830, x[0..4]= 0 0 0 0 0
    &y=0x7fffffffb8e0, y[0..4]= 1.0000 1.0000 1.0000 1.0000 1.0000

    Size=17
    &x=0x5555557d7fd0, x[0..4]= 1.0000 1.0000 1.0000 1.0000 1.0000
    &y=0x5555557d8060, y[0..4]= 0 0 0 0 0
    x.swap(y)
    &x=0x5555557d8060, x[0..4]= 0 0 0 0 0
    &y=0x5555557d7fd0, y[0..4]= 1.0000 1.0000 1.0000 1.0000 1.0000





    share|improve this answer





















      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      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: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      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%2fstackoverflow.com%2fquestions%2f53243845%2farmadillo-does-not-perform-swap-optimization%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      0
      down vote



      accepted










      Looks like armadillo's swap is internally a memcpy below a certain array size (according to op <=16).






      share|improve this answer

























        up vote
        0
        down vote



        accepted










        Looks like armadillo's swap is internally a memcpy below a certain array size (according to op <=16).






        share|improve this answer























          up vote
          0
          down vote



          accepted







          up vote
          0
          down vote



          accepted






          Looks like armadillo's swap is internally a memcpy below a certain array size (according to op <=16).






          share|improve this answer












          Looks like armadillo's swap is internally a memcpy below a certain array size (according to op <=16).







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 11 at 1:36









          OZ17

          17819




          17819
























              up vote
              2
              down vote













              A small expansion of @OZ17's answer.
              Armadillo seems to store data with sizes< 16 locally mem_localand larger ones in an area pointed out by mem



              From GDB:
              > p x
              {
              <arma::Mat<double>> = {
              <arma::Base<double, arma::Mat<double> >> = {
              <arma::Base_inv_yes<arma::Mat<double> >> = {<No data fields>},
              <arma::Base_eval_Mat<double, arma::Mat<double> >> = {<No data fields>},
              <arma::Base_trans_default<arma::Mat<double> >> = {<No data fields>}, <No data fields>},
              members of arma::Mat<double>:
              n_rows = 1,
              n_cols = 10,
              n_elem = 10,
              vec_state = 2,
              mem_state = 0,
              mem = 0x7fffffffb830,
              mem_local = {0 <repeats 16 times>},
              static is_col = false,
              static is_row = false
              },
              members of arma::Row<double>:
              static is_col = false,
              static is_row = false
              }


              and a small example to visualize it:



              arma::rowvec x(10,arma::fill::ones);
              arma::rowvec y(10,arma::fill::zeros);
              std::cout << "Size=10" << std::endl;
              std::cout << "&x=" << x.memptr() << ", x[0..4]=" << x.subvec(1,5);
              std::cout << "&y=" << y.memptr() << ", y[0..4]=" << y.subvec(1,5);
              x.swap(y);
              std::cout << "x.swap(y)" << std::endl;
              std::cout << "&x=" << x.memptr() << ", x[0..4]=" << x.subvec(1,5);
              std::cout << "&y=" << y.memptr() << ", y[0..4]=" << y.subvec(1,5);

              arma::rowvec x2(17,arma::fill::ones);
              arma::rowvec y2(17,arma::fill::zeros);
              std::cout << "nSize=17" << std::endl;
              std::cout << "&x=" << x2.memptr() << ", x[0..4]=" << x2.subvec(1,5);
              std::cout << "&y=" << y2.memptr() << ", y[0..4]=" << y2.subvec(1,5);
              x2.swap(y2);
              std::cout << "x.swap(y)" << std::endl;
              std::cout << "&x=" << x2.memptr() << ", x[0..4]=" << x2.subvec(1,5);
              std::cout << "&y=" << y2.memptr() << ", y[0..4]=" << y2.subvec(1,5);


              The output from the example shows that the content is swapped in both cases but for small arrays it has swapped the local mem area and for the larger case it has swapped the mem pointer.



              Size=10
              &x=0x7fffffffb830, x[0..4]= 1.0000 1.0000 1.0000 1.0000 1.0000
              &y=0x7fffffffb8e0, y[0..4]= 0 0 0 0 0
              x.swap(y)
              &x=0x7fffffffb830, x[0..4]= 0 0 0 0 0
              &y=0x7fffffffb8e0, y[0..4]= 1.0000 1.0000 1.0000 1.0000 1.0000

              Size=17
              &x=0x5555557d7fd0, x[0..4]= 1.0000 1.0000 1.0000 1.0000 1.0000
              &y=0x5555557d8060, y[0..4]= 0 0 0 0 0
              x.swap(y)
              &x=0x5555557d8060, x[0..4]= 0 0 0 0 0
              &y=0x5555557d7fd0, y[0..4]= 1.0000 1.0000 1.0000 1.0000 1.0000





              share|improve this answer

























                up vote
                2
                down vote













                A small expansion of @OZ17's answer.
                Armadillo seems to store data with sizes< 16 locally mem_localand larger ones in an area pointed out by mem



                From GDB:
                > p x
                {
                <arma::Mat<double>> = {
                <arma::Base<double, arma::Mat<double> >> = {
                <arma::Base_inv_yes<arma::Mat<double> >> = {<No data fields>},
                <arma::Base_eval_Mat<double, arma::Mat<double> >> = {<No data fields>},
                <arma::Base_trans_default<arma::Mat<double> >> = {<No data fields>}, <No data fields>},
                members of arma::Mat<double>:
                n_rows = 1,
                n_cols = 10,
                n_elem = 10,
                vec_state = 2,
                mem_state = 0,
                mem = 0x7fffffffb830,
                mem_local = {0 <repeats 16 times>},
                static is_col = false,
                static is_row = false
                },
                members of arma::Row<double>:
                static is_col = false,
                static is_row = false
                }


                and a small example to visualize it:



                arma::rowvec x(10,arma::fill::ones);
                arma::rowvec y(10,arma::fill::zeros);
                std::cout << "Size=10" << std::endl;
                std::cout << "&x=" << x.memptr() << ", x[0..4]=" << x.subvec(1,5);
                std::cout << "&y=" << y.memptr() << ", y[0..4]=" << y.subvec(1,5);
                x.swap(y);
                std::cout << "x.swap(y)" << std::endl;
                std::cout << "&x=" << x.memptr() << ", x[0..4]=" << x.subvec(1,5);
                std::cout << "&y=" << y.memptr() << ", y[0..4]=" << y.subvec(1,5);

                arma::rowvec x2(17,arma::fill::ones);
                arma::rowvec y2(17,arma::fill::zeros);
                std::cout << "nSize=17" << std::endl;
                std::cout << "&x=" << x2.memptr() << ", x[0..4]=" << x2.subvec(1,5);
                std::cout << "&y=" << y2.memptr() << ", y[0..4]=" << y2.subvec(1,5);
                x2.swap(y2);
                std::cout << "x.swap(y)" << std::endl;
                std::cout << "&x=" << x2.memptr() << ", x[0..4]=" << x2.subvec(1,5);
                std::cout << "&y=" << y2.memptr() << ", y[0..4]=" << y2.subvec(1,5);


                The output from the example shows that the content is swapped in both cases but for small arrays it has swapped the local mem area and for the larger case it has swapped the mem pointer.



                Size=10
                &x=0x7fffffffb830, x[0..4]= 1.0000 1.0000 1.0000 1.0000 1.0000
                &y=0x7fffffffb8e0, y[0..4]= 0 0 0 0 0
                x.swap(y)
                &x=0x7fffffffb830, x[0..4]= 0 0 0 0 0
                &y=0x7fffffffb8e0, y[0..4]= 1.0000 1.0000 1.0000 1.0000 1.0000

                Size=17
                &x=0x5555557d7fd0, x[0..4]= 1.0000 1.0000 1.0000 1.0000 1.0000
                &y=0x5555557d8060, y[0..4]= 0 0 0 0 0
                x.swap(y)
                &x=0x5555557d8060, x[0..4]= 0 0 0 0 0
                &y=0x5555557d7fd0, y[0..4]= 1.0000 1.0000 1.0000 1.0000 1.0000





                share|improve this answer























                  up vote
                  2
                  down vote










                  up vote
                  2
                  down vote









                  A small expansion of @OZ17's answer.
                  Armadillo seems to store data with sizes< 16 locally mem_localand larger ones in an area pointed out by mem



                  From GDB:
                  > p x
                  {
                  <arma::Mat<double>> = {
                  <arma::Base<double, arma::Mat<double> >> = {
                  <arma::Base_inv_yes<arma::Mat<double> >> = {<No data fields>},
                  <arma::Base_eval_Mat<double, arma::Mat<double> >> = {<No data fields>},
                  <arma::Base_trans_default<arma::Mat<double> >> = {<No data fields>}, <No data fields>},
                  members of arma::Mat<double>:
                  n_rows = 1,
                  n_cols = 10,
                  n_elem = 10,
                  vec_state = 2,
                  mem_state = 0,
                  mem = 0x7fffffffb830,
                  mem_local = {0 <repeats 16 times>},
                  static is_col = false,
                  static is_row = false
                  },
                  members of arma::Row<double>:
                  static is_col = false,
                  static is_row = false
                  }


                  and a small example to visualize it:



                  arma::rowvec x(10,arma::fill::ones);
                  arma::rowvec y(10,arma::fill::zeros);
                  std::cout << "Size=10" << std::endl;
                  std::cout << "&x=" << x.memptr() << ", x[0..4]=" << x.subvec(1,5);
                  std::cout << "&y=" << y.memptr() << ", y[0..4]=" << y.subvec(1,5);
                  x.swap(y);
                  std::cout << "x.swap(y)" << std::endl;
                  std::cout << "&x=" << x.memptr() << ", x[0..4]=" << x.subvec(1,5);
                  std::cout << "&y=" << y.memptr() << ", y[0..4]=" << y.subvec(1,5);

                  arma::rowvec x2(17,arma::fill::ones);
                  arma::rowvec y2(17,arma::fill::zeros);
                  std::cout << "nSize=17" << std::endl;
                  std::cout << "&x=" << x2.memptr() << ", x[0..4]=" << x2.subvec(1,5);
                  std::cout << "&y=" << y2.memptr() << ", y[0..4]=" << y2.subvec(1,5);
                  x2.swap(y2);
                  std::cout << "x.swap(y)" << std::endl;
                  std::cout << "&x=" << x2.memptr() << ", x[0..4]=" << x2.subvec(1,5);
                  std::cout << "&y=" << y2.memptr() << ", y[0..4]=" << y2.subvec(1,5);


                  The output from the example shows that the content is swapped in both cases but for small arrays it has swapped the local mem area and for the larger case it has swapped the mem pointer.



                  Size=10
                  &x=0x7fffffffb830, x[0..4]= 1.0000 1.0000 1.0000 1.0000 1.0000
                  &y=0x7fffffffb8e0, y[0..4]= 0 0 0 0 0
                  x.swap(y)
                  &x=0x7fffffffb830, x[0..4]= 0 0 0 0 0
                  &y=0x7fffffffb8e0, y[0..4]= 1.0000 1.0000 1.0000 1.0000 1.0000

                  Size=17
                  &x=0x5555557d7fd0, x[0..4]= 1.0000 1.0000 1.0000 1.0000 1.0000
                  &y=0x5555557d8060, y[0..4]= 0 0 0 0 0
                  x.swap(y)
                  &x=0x5555557d8060, x[0..4]= 0 0 0 0 0
                  &y=0x5555557d7fd0, y[0..4]= 1.0000 1.0000 1.0000 1.0000 1.0000





                  share|improve this answer












                  A small expansion of @OZ17's answer.
                  Armadillo seems to store data with sizes< 16 locally mem_localand larger ones in an area pointed out by mem



                  From GDB:
                  > p x
                  {
                  <arma::Mat<double>> = {
                  <arma::Base<double, arma::Mat<double> >> = {
                  <arma::Base_inv_yes<arma::Mat<double> >> = {<No data fields>},
                  <arma::Base_eval_Mat<double, arma::Mat<double> >> = {<No data fields>},
                  <arma::Base_trans_default<arma::Mat<double> >> = {<No data fields>}, <No data fields>},
                  members of arma::Mat<double>:
                  n_rows = 1,
                  n_cols = 10,
                  n_elem = 10,
                  vec_state = 2,
                  mem_state = 0,
                  mem = 0x7fffffffb830,
                  mem_local = {0 <repeats 16 times>},
                  static is_col = false,
                  static is_row = false
                  },
                  members of arma::Row<double>:
                  static is_col = false,
                  static is_row = false
                  }


                  and a small example to visualize it:



                  arma::rowvec x(10,arma::fill::ones);
                  arma::rowvec y(10,arma::fill::zeros);
                  std::cout << "Size=10" << std::endl;
                  std::cout << "&x=" << x.memptr() << ", x[0..4]=" << x.subvec(1,5);
                  std::cout << "&y=" << y.memptr() << ", y[0..4]=" << y.subvec(1,5);
                  x.swap(y);
                  std::cout << "x.swap(y)" << std::endl;
                  std::cout << "&x=" << x.memptr() << ", x[0..4]=" << x.subvec(1,5);
                  std::cout << "&y=" << y.memptr() << ", y[0..4]=" << y.subvec(1,5);

                  arma::rowvec x2(17,arma::fill::ones);
                  arma::rowvec y2(17,arma::fill::zeros);
                  std::cout << "nSize=17" << std::endl;
                  std::cout << "&x=" << x2.memptr() << ", x[0..4]=" << x2.subvec(1,5);
                  std::cout << "&y=" << y2.memptr() << ", y[0..4]=" << y2.subvec(1,5);
                  x2.swap(y2);
                  std::cout << "x.swap(y)" << std::endl;
                  std::cout << "&x=" << x2.memptr() << ", x[0..4]=" << x2.subvec(1,5);
                  std::cout << "&y=" << y2.memptr() << ", y[0..4]=" << y2.subvec(1,5);


                  The output from the example shows that the content is swapped in both cases but for small arrays it has swapped the local mem area and for the larger case it has swapped the mem pointer.



                  Size=10
                  &x=0x7fffffffb830, x[0..4]= 1.0000 1.0000 1.0000 1.0000 1.0000
                  &y=0x7fffffffb8e0, y[0..4]= 0 0 0 0 0
                  x.swap(y)
                  &x=0x7fffffffb830, x[0..4]= 0 0 0 0 0
                  &y=0x7fffffffb8e0, y[0..4]= 1.0000 1.0000 1.0000 1.0000 1.0000

                  Size=17
                  &x=0x5555557d7fd0, x[0..4]= 1.0000 1.0000 1.0000 1.0000 1.0000
                  &y=0x5555557d8060, y[0..4]= 0 0 0 0 0
                  x.swap(y)
                  &x=0x5555557d8060, x[0..4]= 0 0 0 0 0
                  &y=0x5555557d7fd0, y[0..4]= 1.0000 1.0000 1.0000 1.0000 1.0000






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 11 at 9:59









                  Claes Rolen

                  8661416




                  8661416






























                       

                      draft saved


                      draft discarded



















































                       


                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53243845%2farmadillo-does-not-perform-swap-optimization%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Xamarin.iOS Cant Deploy on Iphone

                      Glorious Revolution

                      Dulmage-Mendelsohn matrix decomposition in Python