Intel® oneAPI Threading Building Blocks
Ask questions and share information about adding parallelism to your applications when using this threading library.
Announcements
This community is designed for sharing of public information. Please do not share Intel or third-party confidential information here.

Possible Bugs in TBB Memory Allocators

Shankar1
Beginner
159 Views

I was working with TBB memory allocators and I came across two problemswhich might possibly be bugs.

Problem 1:

The TBB allocators, scalable_allocator and cache_aligned_allocator have defined the allocate methodlike pointer allocate(size_type n, void* hint =0) , while the std::allocator defines the allocatormethod like pointer allocate(size_type _Count, const void _FARQ* hint = 0) because of which i get a compiler error whenIreplacestd::allocator with TBB allocators.I found this problem when I replacedthe default allocator of boost::multi_arraywith TBB allocators.

The TBB memory allocators (both cache_aligned_allocator and scalable _allocator) should also define the second argument of allocate method as const void* as the std::allocator does.This would solve the problem that I found with using TBB allocators with boost::multi_array.

Problem 2:

I found that thecache aligned allocator crashes for the following sample in a 32 bit Windows operating system on a Intel core-2, 1.86GHzmachinebuilt with VisualStudio 2005.The same sample doesnot crash with scalable allocator though.

I made sure that the memory allocator library is available for cache_aligned_allocator to use scalable_malloc instead of malloc but still it crashes.I see the virtual memory of the process increasing and then crashes after a limit.What suprises me is that the problem doesnot happen when i replace the cache_aligned_allocator with scalable_allocator..

I would want to know whether it is really a bug or Im doing something wrong here??

#include
#include
#include "tbb/tick_count.h"
#include "tbb/cache_aligned_allocator.h"

#define KILO 1024
#define MEGA (KILO * KILO)

void allocatorTest(tbb::cache_aligned_allocator& allocator, unsigned int iterations, unsigned int size)
{
std::valarray allocations(iterations);
{
float duration = 0.0;
float time;
unsigned int n = 1;
while (duration < 200.0) {
tbb::tick_count begin = tbb::tick_count::now();
for (unsigned int j = 0; j < n; ++j) {
for (unsigned int i = 0; i < iterations; ++i) {
allocations = allocator.allocate(size);
}
  ; for (unsigned int i = 0; i < iterations; ++i) {
allocator.deallocate( allocations, size);
}
}
tbb::tick_count end = tbb::tick_count::now();
duration = ((end - begin).seconds() *1000);
n += n;
}
n /= 2;
time = ((duration / (n * iterations)) * 1000.0);
std::cout << "cache_aligned_allocator" << " : " << std::setw(5) <<
iterations << ' ' << size << " byte allocs + frees in " << time <<
" micro-seconds per alloc-free pair." << std::endl;
}
}

int main()
{
tbb::cache_aligned_allocator allocator;

allocatorTest(allocator, 1, (64 * KILO));
allocatorTest(allocator, 10, (64 * KILO));
allocatorTest(allocator, 100, (64 * KILO));
allocatorTest(allocator, 1000, (64 * KILO));
allocatorTest(allocator, 10000, (64 * KILO));
allocatorTest(allocator, 1, (1 * MEGA));
allocatorTest(allocator, 10, (1 * MEGA));
allocatorTest(allocator, 100, (1 * MEGA));
allocatorTest(allocator, 1000, (1 * MEGA));
allocatorTest(allocator, 1, (128 * MEGA));
allocatorTest(allocator, 10, (128 * MEGA));
allocatorTest(allocator, 10, (1024 * MEGA));

return 0;
}

0 Kudos
1 Reply
Alexey_M_Intel
Employee
159 Views

Thank you,

I modified all "allocate" functions in TBB, added "const" prefix to "hint" argument. I couldn't change the type of "hint" to const void _FARQ* because it is available only on Windows and the code is not portable in this case.

I suppose the change will appear in the next developer release.

The reason of problem #2 is trying to allocate too much memory. Cache_aligned_allocator throws std::bad_alloc exception in this case. Standard malloc reports error too. Consider changing allocate to malloc in your example:

for

(unsigned int j = 0; j < n; ++j) {

for (unsigned int i = 0; i < iterations; ++i) {

errno = 0;

//allocations = allocator.allocate(size);

allocations = (

char*)malloc(size);

if (errno) {perror("");}

}

for (unsigned int i = 0; i < iterations; ++i) {

//allocator.deallocate( allocations, size);

free (allocations);

}

}

You will get "Not enough space" error messages printed by perror().

Another problem here is the difference in scalable_allocator and cache_aligned_allocator behavior. Cache_aligned_allocator throws an exception, but scalable_allocator doesn't. According to C++ standard, "allocate" method may throw exception if not enough memory is available. We will consider adding exception throwing to scalable_allocator.

Best regards,

Alexey

Reply