Is using alloca() for variable length arrays better than using a vector on the heap?

假如想象 提交于 2019-12-06 12:47:45

You could and probably should use some dynamically allocated heap memory, such as managed by a std::vector (as answered by Peter). You could use smart pointers, or plain raw pointers (new, malloc,....) that you should not forget to release (delete,free,....). Notice that heap allocation is probably faster than what you believe (practically, much less than a microsecond on current laptops most of the time).

Sometimes you can move the allocation out of some inner loop, or grow it only occasionally (so for a realloc-like thing, better use unsigned newsize=5*oldsize/4+10; than unsigned newsize=oldsize+1; i.e. have some geometrical growth). If you can't use vectors, be sure to keep separate allocated size and used lengths (as std::vector does internally).

Another strategy would be to special case small sizes vs bigger ones. e.g. for an array less than 30 elements, use the call stack; for bigger ones, use the heap.

If you insist on allocating (using VLAs -they are a commonly available extension of standard C++11- or alloca) on the call stack, be wise to limit your call frame to a few kilobytes. The total call stack is limited (e.g. often to about a megabyte or a few of them on many laptops) to some implementation specific limit. In some OSes you can raise that limit (see also setrlimit(2) on Linux)

Be sure to benchmark before hand-tuning your code. Don't forget to enable compiler optimization (e.g. g++ -O2 -Wall with GCC) before benchmarking. Remember that caches misses are generally much more expensive than heap allocation. Don't forget that developer's time also has some cost (which often is comparable to cumulated hardware costs).

Notice that using static variable or data has also issues (it is not reentrant, not thread safe, not async-signal-safe -see signal-safety(7) ....) and is less readable and less robust.

Peter

First of all, you're getting lucky if your code compiles with ANY C++ compiler as is. VLAs are not standard C++. Some compilers support them as an extension.

Using alloca() is also not standard, so is not guaranteed to work reliably (or even at all) when using different compilers.

Using a static vector is inadvisable in many cases. In your case, it gives behaviour that is potentially not equivalent to the original code.

A third option you may wish to consider is

 // in definition of class Test
void somemethod()
{
    std::vector<int> array(P);      // assume preceding #include <vector>
    // do something with array
}

A vector is essentially a dynamically allocated array, but will be cleaned up properly in the above when the function returns.

The above is standard C++. Unless you perform rigorous testing and profiling that provides evidence of a performance concern this should be sufficient.

Why don't you make the array a private member?

#include <vector>

class Test
{
public:
    Test()
    {
        data_.resize(5);
    }
    void somemethod()
    {
        // do something with data_
    }
private:
    std::vector<int> data_;
}

As you've specified a likely maximum size of the array, you could also look at something like boost::small_vector, which could be used like:

#include <boost/container/small_vector.hpp>

class Test
{
public:
    Test()
    {
        data_.resize(5);
    }
    void somemethod()
    {
        // do something with data_
    }
private:
    using boc = boost::container;

    constexpr std::size_t preset_capacity_ = 400;
    boc::small_vector<int, preset_capacity_> data_;
}

You should profile to see if this is actually better, and be aware this will likely use more memory, which could be an issue if there are many Test instances.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!