concurrent_vector, shrink_to_fit(), compact()

TCE Options

TCE Level: 

TCE Open Date: 

Thursday, February 6, 2020 - 01:08

concurrent_vector, shrink_to_fit(), compact()

Hi All.

1. concurrent_vector.h mentions compact() method:

@par Changes since TBB 2.0
    - Added compact() method to defragment first segments

But there's no such method.

2. Doc at states: " The method shrink_to_fit()merges several smaller arrays into a single contiguous array, which may improve access time."
But I found shrink_to_fit() doesn't create a single continuous array, and I need single contiguous array to use older API that expects pointers.

version info:

// Marketing-driven product version
#define TBB_VERSION_MAJOR 2019

// Engineering-focused interface version

Any insights to alleviate my confusion?


4 posts / 0 new




The compact() still shows up in documentation. I have to check why it is the case. My search  shows: "Method shrink_to_fit was called compact() in Intel® TBB 2.1. It was renamed to match the C++0x std::vector::shrink_to_fit()."

I see also in documentation; "The method shrink_to_fit()merges several smaller arrays into a single contiguous array, which may improve access time."

However, you report that shrink_to_fit() "doesn't create a single continuous array". How did you come to this conclusion?

I picked some samples from the web and constructed a sample to experiment with:

#include <iostream>
#include <stdio.h>
#include <tbb/task_scheduler_init.h>
#include <tbb/blocked_range.h>
#include <tbb/parallel_for.h>
#include <tbb/concurrent_vector.h>
#include <tbb/blocked_range.h>

#define N 24

using namespace std;
using namespace tbb;

template<class I>
bool is_contiguous(I first, I last)
    auto test = true;
    auto const n = std::distance(first, last);
    for (auto i = 0; i < n && test; ++i) {
        test &= *(std::next(first, i)) == *(std::next(std::addressof(*first), i));
    return test;

class FObject {
        concurrent_vector<int> &cv;

        FObject( concurrent_vector<int> &_cv ) : cv( _cv ) {}

        void operator( )( const blocked_range<size_t>& r ) const {

            printf("%08d - %08d\n",r.begin(),r.end());

            for ( size_t i=r.begin(); i!=r.end( ); ++i ) {

void par_func(int x, int y, concurrent_vector<int> &cv)
    FObject ob(cv);


int main()
    task_scheduler_init init(2);

    concurrent_vector<int> cv;


    cout << cv.size() << endl;

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

    std::cout << std::boolalpha << is_contiguous(cv.begin(), cv.end()) << "\n";

    return 0;

when I comment out cv.shrink_to_fit(); I'm getting "false" while with cv.shrink_to_fit(); I got "true". This was done with TBB 2019 







As documented, method concurrent_vector::shrink_to_fit merges several internal arrays of elements into the single one. So the vector becomes continuous .

But if you then adds some new elements into the vector (with any growth operation), the new elements can be placed into the new array, so the whole vector is not continuous any more.


concurrent_vector<int> cv(10); // continuous vector


// cv is not continuous after the grow_by call


// several arrays were merged, so cv is continuous again


// cv can be not continuous again, so an other shrink_to_fit call is required

Best regards,

That's the class I used:

template<typename T>
class buffer

    buffer() = default;
    buffer(const buffer&) = delete;
    buffer& operator= (const buffer&) = delete;

    void resize(size_t newSize)
        m_compacted = false;
    operator const T* () const // not multithreaded !!! invalidates all iterators/pointers!!!
        if (!m_compacted)
#ifdef _IT_WORKS_
            tbb::concurrent_vector<T> temp(m_Vec.size());
            std::copy(m_Vec.cbegin(), m_Vec.cend(), temp.begin());
#else // it doesn't work
            m_compacted = true;
        return &m_Vec.front();
    const T& operator[](size_t i) const
        return m_Vec[i];
    T& operator[](size_t i)
        return m_Vec[i];
    auto cbegin() const
        return m_Vec.cbegin();
    auto cend() const
        return m_Vec.cend();
    auto begin() const
        return m_Vec.begin();
    auto end() const
        return m_Vec.end();
    auto size() const
        return m_Vec.size();
    mutable tbb::concurrent_vector<T> m_Vec;
    mutable bool m_compacted = false;

   buffer aBuffer;

  // ...added data to aBuffer...

    const int* p = aBuffer;

    int val;
    for (int i = 0; i < aBuffer.size(); ++i)
        val = p[i] ;

works with _IT_WORKS_ defined.

with _IT_WORKS_ undefined I can see *p at position 1024 is wrong (less then 0 while it can't). All values in aBuffer in range 0..1023 are valid,


___I was not able to reproduce this problem in a sandbox.___


Leave a Comment

Please sign in to add a comment. Not a member? Join today