Intel® oneAPI Threading Building Blocks
Ask questions and share information about adding parallelism to your applications when using this threading library.

Push_back API concurrent vector

PritamLakhmani
Beginner
857 Views

Hi,

Through push_back API of concurrent vector container, I tried to push_back around (10000000) my custom objects, my sample application is a single threaded application.

I tested push_back API, through two tbb versions , first one is old tbb (version libtbb2.4.2~20130725) & second one is new oneapi tbb (version oneapi-tbb-2021.5.0-lin.tgz).

Through oneapi tbb (oneapi-tbb-2021.5.0-lin.tgz)),Time taken by push_back API in pushing 10000000 custom objects is approximately twice than time taken by push_back API of old tbb (libtbb2.4.2~20130725).

I am using Ubuntu 20.04.5 version on my desktop PC. As per my view, time taken by latest oneapi tbb APIs should be less than (or equal) to the time taken by old tbb APIs.

 

Pls suggest.
Regards,
Pritam

0 Kudos
22 Replies
SeshaP_Intel
Moderator
819 Views

Hi,


Thank you for posting in Intel Communities.


Could you please try with the oneTBB latest version oneTBB 2021.6.0? 

If you still face any issues please share the sample reproducer code and steps to reproduce so that we can investigate the issue more from our end.


Thanks and Regards,

Pendyala Sesha Srinivas



PritamLakhmani
Beginner
770 Views

Hi,

Thanks for your suggestions. We have tried to implement your suggested solutions for push_back around (10000000) on my custom objects, my sample application is a single threaded application.

I tested push_back API, through two tbb versions , first one is old tbb (version libtbb2.4.2~20130725) & second one is new oneapi tbb (version oneapi-tbb-2021.6.0-lin.tgz). 

 

We are still getting same result as we were getting with oneapi-tbb-2021.5.0-lin.tgz.

 

Through oneapi tbb (oneapi-tbb-2021.6.0-lin.tgz)),Time taken by push_back API in pushing 10000000 custom objects is approximately twice than time taken by push_back API of old tbb (libtbb2.4.2~20130725).

I am using Ubuntu 20.04.5 version on my desktop PC. As per my view, time taken by latest oneapi tbb APIs should be less than (or equal) to the time taken by old tbb APIs.

 

I also attached my sample code which we used in latest new tbb (oneapi-tbb-2021.6.0-lin.tgz) and in old tbb (libtbb2.4.2~20130725). Please check them also.  

 

Old tbb test file : https://docs.google.com/document/d/1CS5GFwUWvCIGlLRgq0EIjdKnZWe7EqIm4IrZzUg4JXI/edit?usp=sharing

New tbb test file : https://docs.google.com/document/d/1igsfphznDs3RRbkFw09K0EthEsv7Bfn_6_z5Ooo2EG8/edit?usp=sharing 

PritamLakhmani
Beginner
744 Views

Can you please check this now , We have shared code and step regarding push_back . We are facing kind of blockages in our work due to this time diffrence in Old and New TBB.

SeshaP_Intel
Moderator
708 Views

Hi,

 

We have tested push_back API with both codes you have provided.

We tried using the latest version oneTBB 2021.6.0 and compared the results with tbb 2013.1.046, 2013.0.028 versions.

As per the results generated, the time taken to compute push_back API with the latest oneTBB 2021.6.0 was lesser than tbb 2013.1.046, 2013.0.028 versions.

Please find the attached screenshots of the results.

Result from oneTBB 2021.6.0 version

2021.6.png

Result from tbb 2013.1.046 version

2013.1.png

Result from tbb 2013.0.028 version

2013.0.png

 

Please let us know if you still face any issues. 

 

Thanks and Regards,

Pendyala Sesha Srinivas

 

PritamLakhmani
Beginner
668 Views

Hi, 

Thanks for yor testing and support on our query . But we are still getting same result's as before like in new tbb (oneapi-tbb-2021.6.0-lin.tgz) we are still getting arround 1.04 secs.

 

user@test:~/newtbb/test$ g++ new_tbb_push_back.cpp -o test -ltbb -std=c++17
user@test:~/newtbb/test$ ./test
Start push_back
Time taken by program is : 1.047868 sec

 

Can you please tell us reason behind using icpx  for new tbb(oneapi-tbb-2021.6.0-lin.tgz) and g++ for older one (tbb 2013.1.046, 2013.0.028 version) because we were using g++ for both new and old and  using diffrent compilers can create performance diffrence with TBB library?

 

Also can you please share your testing environment datails like machine os version, compilers name and there versions? So we can match with ours and test with same environment because we are still getting higher time.

 

 

SeshaP_Intel
Moderator
623 Views

Hi,


We have tested your code on Rocky Linux (Version 8.6).

We have used icpx(2022.1.0) while using the OneTBB 2021.6.0 version because we observed good performance with icpx whereas for the old TBB version we tried with g++ as icpx is not supported.


Thanks and Regards,

Pendyala Sesha Srinivas


PritamLakhmani
Beginner
612 Views

Hi,

Thanks you for sharing this info. As you mentioned you have tested our code in Rocky Linux (Version 8.6) where results are coming fine.  As we prviously also shared we are using Linux  Ubuntu 20.04.4 LTS and in Ubuntu 20.04.4 LTS we are getting high performance time in latest one api tbb(version oneapi-tbb-2021.6.0-lin.tgz)

 

So,  if possible can you please share results tesing in Ubuntu 20.04.4 LTS Linux machine and using g++ compiler of our sample code. 

 

Also can you please share how we can setup icpx compiler in Ubuntu 20.04.4 LTS Linux system.

SeshaP_Intel
Moderator
575 Views

Hi,

 

We have tested your new TBB source file using the g++ compiler and observed that the new TBB source file takes more time. 

Please find the below screenshot for the result.

SeshaP_Intel_0-1665571683731.png

 

We were able to reproduce it and we have informed the development team about it.

You can refer to the below link for installing icpx compiler.

https://www.intel.com/content/www/us/en/developer/articles/tool/oneapi-standalone-components.html#in...

 

Thanks and Regards,

Pendyala Sesha Srinivas

 

 

PritamLakhmani
Beginner
526 Views

Hi,

Thankyou for this testing. I have one query regarding new onetbb library and g++ compiler. I want to know that , Is there some anyway or method or steps by which we can get lesser time with new onetbb library while using g++  compiler. I know we are getting better timing with icpx compiler but i want to know is there some way  we  can get better timing with g++ compiler with new oneTbb library. 

PritamLakhmani
Beginner
461 Views

Hi, 

I have one query regarding old and New tbb. 

In older tbb there is push_back function, when we insert in vector using push_back function it can return iterrator or index of element while inserting it.  

 

Old Tbb push_back function : 

#if TBB_DEPRECATED
    size_type push_back( const_reference item )
#else
    /** Returns iterator pointing to the new element. */
    iterator push_back( const_reference item )
#endif
    {
        size_type k;
        void *ptr = internal_push_back(sizeof(T),k);
        internal_loop_guide loop(1, ptr);
        loop.init(&item);
#if TBB_DEPRECATED
        return k;
#else
        return iterator(*this, k, ptr);
#endif
 
 
But in new tbb it only return iterator of that element while inserting 
 
template <typename... Args>
    iterator internal_emplace_back( Args&&... args ) {
        size_type old_size = this->my_size++;
        this->assign_first_block_if_necessary(default_first_block_size);
        auto element_address = &base_type::template internal_subscript</*allow_out_of_range_access=*/true>(old_size);

        // try_call API is not convenient here due to broken
        // variadic capture on GCC 4.8.5
        auto value_guard = make_raii_guard([&] {
            zero_unconstructed_elements(element_address, /*count =*/1);
        });

        segment_table_allocator_traits::construct(base_type::get_allocator(), element_address, std::forward<Args>(args)...);
        value_guard.dismiss();
        return iterator(*this, old_size, element_address);
    }
 
iterator push_back( const value_type& item ) {
        return internal_emplace_back(item);
    }
 
So my query is that is there any way or api from which we can get index of element while inserting it. I know we can do it by using std::distance function but it is O(n) operation and it is very costly for us. So please tell us if there is any function or api from which we can get indeses of inserting elements.
 
 
 
SeshaP_Intel
Moderator
271 Views

Hi,


We are working on your issue internally. We will get back to you soon.


Thanks and Regards,

Pendyala Sesha Srinivas


SeshaP_Intel
Moderator
239 Views

Hi,


Could you please let us know what was the rationale in creating 2 different versions?


Thanks and Regards,

Pendyala Sesha Srinivas


Mark_L_Intel
Employee
210 Views

Hello,

 

   Have you used optimizations flags? With -O1 (or -O2, -O3)

 

    g++ -O1 new_tbb.cpp -o gpb.x -ltbb

    icpx -O1 new_tbb.cpp -o ipb.x -tbb

 

   I got in both cases ~ 0.7 sec.

  

PritamLakhmani
Beginner
143 Views

Sorry for late reply,

Yes we have tried optimization flags and timings are also similar  in old and new tbb. But we have one more query regarding push_back function. 

 

 

SeshaP_Intel
Moderator
189 Views

Hi,


We haven't heard back from you. Could you please provide an update on your issue?


Thanks and Regards,

Pendyala Sesha Srinivas


PritamLakhmani
Beginner
141 Views

Hi, 

I have one query regarding old and New tbb. 

In older tbb there is push_back function, when we insert in vector using push_back function it can return iterrator or index of element while inserting it.  

 

Old Tbb push_back function : 

#if TBB_DEPRECATED
    size_type push_back( const_reference item )
#else
    /** Returns iterator pointing to the new element. */
    iterator push_back( const_reference item )
#endif
    {
        size_type k;
        void *ptr = internal_push_back(sizeof(T),k);
        internal_loop_guide loop(1, ptr);
        loop.init(&item);
#if TBB_DEPRECATED
        return k;
#else
        return iterator(*this, k, ptr);
#endif
 
 
But in new tbb it only return iterator of that element while inserting 
 
template <typename... Args>
    iterator internal_emplace_back( Args&&... args ) {
        size_type old_size = this->my_size++;
        this->assign_first_block_if_necessary(default_first_block_size);
        auto element_address = &base_type::template internal_subscript</*allow_out_of_range_access=*/true>(old_size);

        // try_call API is not convenient here due to broken
        // variadic capture on GCC 4.8.5
        auto value_guard = make_raii_guard([&] {
            zero_unconstructed_elements(element_address, /*count =*/1);
        });

        segment_table_allocator_traits::construct(base_type::get_allocator(), element_address, std::forward<Args>(args)...);
        value_guard.dismiss();
        return iterator(*this, old_size, element_address);
    }
 
iterator push_back( const value_type& item ) {
        return internal_emplace_back(item);
    }
 
So my query is that is there any way or api from which we can get index of element while inserting it. I know we can do it by using std::distance function but it is O(n) operation and it is very costly for us. So please tell us if there is any function or api from which we can get indeses of inserting elements.
 
 
 
Can you please check query ? 
Mark_L_Intel
Employee
133 Views

Access by index is available:

 https://spec.oneapi.io/versions/latest/elements/oneTBB/source/containers/concurrent_vector_cls/eleme...

 

For example, consider this example, tbb_concurrent_v.cpp:

#include <iostream>
#include <oneapi/tbb.h>

int main(int argc, char** argv){

  tbb::concurrent_vector<int> conc_vec;

  int size = 10;

  tbb::parallel_for(0, size, 1, [&](int i){
      conc_vec.push_back(i);
    });

   for(int i = 0; i < conc_vec.size(); i++)
    printf(" %d", conc_vec[i]);
   printf("\n");

}

 

After compiling:

  icpx tbb_concurrent_v.cpp -tbb

the executable produces:

./a.out
0 1 2 3 4 5 6 7 8 9

 

 

 

 

PritamLakhmani
Beginner
111 Views

Hello,

Thankyou for your help on this. We are already using this Access by index in vector for getting getting element in i'th index. my query is 

in old tbb while we do push_back in any vector in return it gives us index of that indexed element which is index of last inserted element.

 

if you check of code of old tbb push_back: 

 

 

#if TBB_DEPRECATED
    size_type push_backconst_reference item )
#else
    /** Returns iterator pointing to the new element. */
    iterator push_backconst_reference item )
#endif
    {
        size_type k;
        void *ptr = internal_push_back(sizeof(T),k);
        internal_loop_guide loop(1ptr);
        loop.init(&item);
#if TBB_DEPRECATED
        return k;
#else
        return iterator(*this, k, ptr);
#endif

 

In this function k variable returning index of last inserted element in vector.

but if we see push_back function in new tbb : 

 

template <typename... Args>
    iterator internal_emplace_backArgs&&... args ) {
        size_type old_size = this->my_size++;
        this->assign_first_block_if_necessary(default_first_block_size);
        auto element_address = &base_type::template internal_subscript</*allow_out_of_range_access=*/true>(old_size);

        // try_call API is not convenient here due to broken
        // variadic capture on GCC 4.8.5
        auto value_guard = make_raii_guard([&] {
            zero_unconstructed_elements(element_address, /*count =*/1);
        });

        segment_table_allocator_traits::construct(base_type::get_allocator(), element_addressstd::forward<Args>(args)...);
        value_guard.dismiss();
        return iterator(*this, old_size, element_address);
    }
 
iterator push_backconst value_type& item ) {
        return internal_emplace_back(item);
    }

 

 

there is no option to return index of elemnent which is last inserted in vector while we push_back.

 

Please share if there any way we can get index of elements direclty while we push_back that element.

 

 demo code : 

 

    vector<my_data_structure> sample_vector;

    int sizes = sample_vector.size();

    index_of_pushed_element = sample_vector.push_back(my_data_structure_element);

    // index_of_pushed_element should be equal to (sizes + 1) 

 

please share any way by which we can get get index of last inserted element.

    

 

 

 

 

 

Mark_L_Intel
Employee
90 Views
#include <iostream>
#include <oneapi/tbb.h>

int main(int argc, char** argv){

  tbb::concurrent_vector<int> conc_vec;
  tbb::concurrent_vector<int>::iterator it;
  int index_of_pushed_element;

  int size = 10;

  tbb::parallel_for(0, size, 1, [&](int i){
      it = conc_vec.push_back(i);
      index_of_pushed_element = *it;
      std::cout << "index_of_pushed_element = " << index_of_pushed_element << "\n";
    });

   for(int i = 0; i < conc_vec.size(); i++)
    printf(" %d", conc_vec[i]);
   printf("\n");

}

produces:

./a.out
index_of_pushed_element = 0
index_of_pushed_element = 1
index_of_pushed_element = 2
index_of_pushed_element = 3
index_of_pushed_element = 4
index_of_pushed_element = 5
index_of_pushed_element = 6
index_of_pushed_element = 7
index_of_pushed_element = 8
index_of_pushed_element = 9
 0 1 2 3 4 5 6 7 8 9

 

PritamLakhmani
Beginner
39 Views

Hi,

Thanks for your solution but i think *it in line no 14 of your sample code gives value of element not the index.

 

check  there : https://www.geeksforgeeks.org/input-iterators-in-cpp/#:~:text=Dereferencing%3A%20An%20input%20iterat...().

 Dereferencing: An input iterator can be dereferenced, using the operator * and -> as an rvalue to obtain the value stored at the position                being pointed to by the iterator.

 

I also tried running your sample code with diffrent values.

 

#include <iostream>

#include <oneapi/tbb.h>

int main(int argc, char** argv)

     tbb::concurrent_vector<int> conc_vec;

     tbb::concurrent_vector<int>::iterator it;

      int index_of_pushed_element;

      int size = 10;

      tbb::parallel_for(5, size, 1, [&](int i){

      it = conc_vec.push_back(i);

      index_of_pushed_element = *it;

      std::cout << "index_of_pushed_element = " << index_of_pushed_element << "\n";

     });

 

    for(int i = 0; i < conc_vec.size(); i++)

      printf(" %d", conc_vec[i]);

     printf("\n"); }

 

 

output of above code is: 

index_of_pushed_element = 5

index_of_pushed_element = 6

index_of_pushed_element = 7

index_of_pushed_element = 8

index_of_pushed_element = 9

 5 6 7 8 9

but it should be like : 

output of above code is: 

index_of_pushed_element = 0

index_of_pushed_element = 1

index_of_pushed_element = 2

index_of_pushed_element = 3

index_of_pushed_element = 4

 5 6 7 8 9

 

my query is how to remove one element from concurrent_vector?

Reply