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

Possible Bugs in TBB Memory Allocators

Shankar1
Beginner
302 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
302 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

0 Kudos
Reply