Does C++17 offer generators or another built-in way to transform a non-instantiated sequence in parallel?









up vote
1
down vote

favorite












I'm trying to transform a sequence of numbers in parallel in C++17 and store the results in a vector. But so far I'm unable to find a way to represent the sequence without explicitly filling an array with it, like so:



void transformRange(size_t N)

// Want to replace nums with a generator (an iterator that is not associated with a container)
std::vector<size_t> nums(N);
std::iota(nums.begin(), nums.end(), 0);

std::vector<size_t> a(N);
std::transform(std::execution::par, nums.begin(), nums.end(), a.begin(), fun);



I want this to be doable in parallel (hence the std::execution::par), and the above transform does work in parallel, but the iota does not and it's 3X the memory bandwidth.



I'm also open to deriving the sequence number from the reference to the value being transformed, but I can't get the syntax right. Something like:



void transformRange2(size_t N)

std::vector<size_t> a(N);
std::transform(std::execution::par, a.begin(), a.end(), a.begin(), [&](auto & i) fun(&i - a.begin()); );










share|improve this question























  • You can use std::distance to create the index of an iterator: stackoverflow.com/questions/2152986/…
    – José Manuel Ramos
    Nov 10 at 21:29














up vote
1
down vote

favorite












I'm trying to transform a sequence of numbers in parallel in C++17 and store the results in a vector. But so far I'm unable to find a way to represent the sequence without explicitly filling an array with it, like so:



void transformRange(size_t N)

// Want to replace nums with a generator (an iterator that is not associated with a container)
std::vector<size_t> nums(N);
std::iota(nums.begin(), nums.end(), 0);

std::vector<size_t> a(N);
std::transform(std::execution::par, nums.begin(), nums.end(), a.begin(), fun);



I want this to be doable in parallel (hence the std::execution::par), and the above transform does work in parallel, but the iota does not and it's 3X the memory bandwidth.



I'm also open to deriving the sequence number from the reference to the value being transformed, but I can't get the syntax right. Something like:



void transformRange2(size_t N)

std::vector<size_t> a(N);
std::transform(std::execution::par, a.begin(), a.end(), a.begin(), [&](auto & i) fun(&i - a.begin()); );










share|improve this question























  • You can use std::distance to create the index of an iterator: stackoverflow.com/questions/2152986/…
    – José Manuel Ramos
    Nov 10 at 21:29












up vote
1
down vote

favorite









up vote
1
down vote

favorite











I'm trying to transform a sequence of numbers in parallel in C++17 and store the results in a vector. But so far I'm unable to find a way to represent the sequence without explicitly filling an array with it, like so:



void transformRange(size_t N)

// Want to replace nums with a generator (an iterator that is not associated with a container)
std::vector<size_t> nums(N);
std::iota(nums.begin(), nums.end(), 0);

std::vector<size_t> a(N);
std::transform(std::execution::par, nums.begin(), nums.end(), a.begin(), fun);



I want this to be doable in parallel (hence the std::execution::par), and the above transform does work in parallel, but the iota does not and it's 3X the memory bandwidth.



I'm also open to deriving the sequence number from the reference to the value being transformed, but I can't get the syntax right. Something like:



void transformRange2(size_t N)

std::vector<size_t> a(N);
std::transform(std::execution::par, a.begin(), a.end(), a.begin(), [&](auto & i) fun(&i - a.begin()); );










share|improve this question















I'm trying to transform a sequence of numbers in parallel in C++17 and store the results in a vector. But so far I'm unable to find a way to represent the sequence without explicitly filling an array with it, like so:



void transformRange(size_t N)

// Want to replace nums with a generator (an iterator that is not associated with a container)
std::vector<size_t> nums(N);
std::iota(nums.begin(), nums.end(), 0);

std::vector<size_t> a(N);
std::transform(std::execution::par, nums.begin(), nums.end(), a.begin(), fun);



I want this to be doable in parallel (hence the std::execution::par), and the above transform does work in parallel, but the iota does not and it's 3X the memory bandwidth.



I'm also open to deriving the sequence number from the reference to the value being transformed, but I can't get the syntax right. Something like:



void transformRange2(size_t N)

std::vector<size_t> a(N);
std::transform(std::execution::par, a.begin(), a.end(), a.begin(), [&](auto & i) fun(&i - a.begin()); );







c++ range c++17 lazy-evaluation lazy-sequences






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 10 at 21:40









Deduplicator

33.9k64787




33.9k64787










asked Nov 10 at 20:57









All the Rage

16411




16411











  • You can use std::distance to create the index of an iterator: stackoverflow.com/questions/2152986/…
    – José Manuel Ramos
    Nov 10 at 21:29
















  • You can use std::distance to create the index of an iterator: stackoverflow.com/questions/2152986/…
    – José Manuel Ramos
    Nov 10 at 21:29















You can use std::distance to create the index of an iterator: stackoverflow.com/questions/2152986/…
– José Manuel Ramos
Nov 10 at 21:29




You can use std::distance to create the index of an iterator: stackoverflow.com/questions/2152986/…
– José Manuel Ramos
Nov 10 at 21:29












2 Answers
2






active

oldest

votes

















up vote
1
down vote













Ranges not backed by a container (or the nightmare called std::vector<bool>) are not part of C++17.



But don't despair, Boost provides the counting_iterator, just what you need for a lazy range.



It even provides it conveniently packaged as a range using counting_range.






share|improve this answer




















  • Why is std::vector<bool> a nightmare and why is it not part of C++17?
    – V0ldek
    Nov 10 at 21:48






  • 2




    @V0ldek Well, the ranges TS might make it into C++20, as might concepts. (Huh, I'm not quite sure a counting-range is actually part of that. Oh well.) And std::vector<bool> is a nightmare because it is not really a std::vector, as it has a very different interface, nor is it really a contyiner. There are good posts on SO going further into it than a comment should try.
    – Deduplicator
    Nov 10 at 21:51


















up vote
0
down vote













template<class F, class R=std::result_of_t<F&(std::size_t)>>
std::vector<R> rangeFromIndex(F&& f, std::size_t N)

std::vector<R> a(N);
std::for_each(std::execution::par,
a.begin(), a.end(),
[&](auto & i) i = fun(std::size_t(std::addressof(i) - a.data()));
);



that should do it.






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%2f53243343%2fdoes-c17-offer-generators-or-another-built-in-way-to-transform-a-non-instantia%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
    1
    down vote













    Ranges not backed by a container (or the nightmare called std::vector<bool>) are not part of C++17.



    But don't despair, Boost provides the counting_iterator, just what you need for a lazy range.



    It even provides it conveniently packaged as a range using counting_range.






    share|improve this answer




















    • Why is std::vector<bool> a nightmare and why is it not part of C++17?
      – V0ldek
      Nov 10 at 21:48






    • 2




      @V0ldek Well, the ranges TS might make it into C++20, as might concepts. (Huh, I'm not quite sure a counting-range is actually part of that. Oh well.) And std::vector<bool> is a nightmare because it is not really a std::vector, as it has a very different interface, nor is it really a contyiner. There are good posts on SO going further into it than a comment should try.
      – Deduplicator
      Nov 10 at 21:51















    up vote
    1
    down vote













    Ranges not backed by a container (or the nightmare called std::vector<bool>) are not part of C++17.



    But don't despair, Boost provides the counting_iterator, just what you need for a lazy range.



    It even provides it conveniently packaged as a range using counting_range.






    share|improve this answer




















    • Why is std::vector<bool> a nightmare and why is it not part of C++17?
      – V0ldek
      Nov 10 at 21:48






    • 2




      @V0ldek Well, the ranges TS might make it into C++20, as might concepts. (Huh, I'm not quite sure a counting-range is actually part of that. Oh well.) And std::vector<bool> is a nightmare because it is not really a std::vector, as it has a very different interface, nor is it really a contyiner. There are good posts on SO going further into it than a comment should try.
      – Deduplicator
      Nov 10 at 21:51













    up vote
    1
    down vote










    up vote
    1
    down vote









    Ranges not backed by a container (or the nightmare called std::vector<bool>) are not part of C++17.



    But don't despair, Boost provides the counting_iterator, just what you need for a lazy range.



    It even provides it conveniently packaged as a range using counting_range.






    share|improve this answer












    Ranges not backed by a container (or the nightmare called std::vector<bool>) are not part of C++17.



    But don't despair, Boost provides the counting_iterator, just what you need for a lazy range.



    It even provides it conveniently packaged as a range using counting_range.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Nov 10 at 21:39









    Deduplicator

    33.9k64787




    33.9k64787











    • Why is std::vector<bool> a nightmare and why is it not part of C++17?
      – V0ldek
      Nov 10 at 21:48






    • 2




      @V0ldek Well, the ranges TS might make it into C++20, as might concepts. (Huh, I'm not quite sure a counting-range is actually part of that. Oh well.) And std::vector<bool> is a nightmare because it is not really a std::vector, as it has a very different interface, nor is it really a contyiner. There are good posts on SO going further into it than a comment should try.
      – Deduplicator
      Nov 10 at 21:51

















    • Why is std::vector<bool> a nightmare and why is it not part of C++17?
      – V0ldek
      Nov 10 at 21:48






    • 2




      @V0ldek Well, the ranges TS might make it into C++20, as might concepts. (Huh, I'm not quite sure a counting-range is actually part of that. Oh well.) And std::vector<bool> is a nightmare because it is not really a std::vector, as it has a very different interface, nor is it really a contyiner. There are good posts on SO going further into it than a comment should try.
      – Deduplicator
      Nov 10 at 21:51
















    Why is std::vector<bool> a nightmare and why is it not part of C++17?
    – V0ldek
    Nov 10 at 21:48




    Why is std::vector<bool> a nightmare and why is it not part of C++17?
    – V0ldek
    Nov 10 at 21:48




    2




    2




    @V0ldek Well, the ranges TS might make it into C++20, as might concepts. (Huh, I'm not quite sure a counting-range is actually part of that. Oh well.) And std::vector<bool> is a nightmare because it is not really a std::vector, as it has a very different interface, nor is it really a contyiner. There are good posts on SO going further into it than a comment should try.
    – Deduplicator
    Nov 10 at 21:51





    @V0ldek Well, the ranges TS might make it into C++20, as might concepts. (Huh, I'm not quite sure a counting-range is actually part of that. Oh well.) And std::vector<bool> is a nightmare because it is not really a std::vector, as it has a very different interface, nor is it really a contyiner. There are good posts on SO going further into it than a comment should try.
    – Deduplicator
    Nov 10 at 21:51













    up vote
    0
    down vote













    template<class F, class R=std::result_of_t<F&(std::size_t)>>
    std::vector<R> rangeFromIndex(F&& f, std::size_t N)

    std::vector<R> a(N);
    std::for_each(std::execution::par,
    a.begin(), a.end(),
    [&](auto & i) i = fun(std::size_t(std::addressof(i) - a.data()));
    );



    that should do it.






    share|improve this answer
























      up vote
      0
      down vote













      template<class F, class R=std::result_of_t<F&(std::size_t)>>
      std::vector<R> rangeFromIndex(F&& f, std::size_t N)

      std::vector<R> a(N);
      std::for_each(std::execution::par,
      a.begin(), a.end(),
      [&](auto & i) i = fun(std::size_t(std::addressof(i) - a.data()));
      );



      that should do it.






      share|improve this answer






















        up vote
        0
        down vote










        up vote
        0
        down vote









        template<class F, class R=std::result_of_t<F&(std::size_t)>>
        std::vector<R> rangeFromIndex(F&& f, std::size_t N)

        std::vector<R> a(N);
        std::for_each(std::execution::par,
        a.begin(), a.end(),
        [&](auto & i) i = fun(std::size_t(std::addressof(i) - a.data()));
        );



        that should do it.






        share|improve this answer












        template<class F, class R=std::result_of_t<F&(std::size_t)>>
        std::vector<R> rangeFromIndex(F&& f, std::size_t N)

        std::vector<R> a(N);
        std::for_each(std::execution::par,
        a.begin(), a.end(),
        [&](auto & i) i = fun(std::size_t(std::addressof(i) - a.data()));
        );



        that should do it.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 11 at 3:44









        Yakk - Adam Nevraumont

        179k19186365




        179k19186365



























             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53243343%2fdoes-c17-offer-generators-or-another-built-in-way-to-transform-a-non-instantia%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







            這個網誌中的熱門文章

            What does pagestruct do in Eviews?

            Dutch intervention in Lombok and Karangasem

            Channel Islands