0

我想为非静态成员模拟线程局部变量,如下所示:

template< typename T, unsigned int tNumThread >
class ThreadLocal
{
private:

protected:
    T mData[tNumThread];

    unsigned int _getThreadIndex()
    {
        return ...; // i have a threadpool and each thread has an index from 0 to n
    }

public:
    ThreadLocal() {};
    ~ThreadLocal() {};

    T& operator ->()
    {
        return mData[_getThreadIndex()];
    }
    ...
};

但问题是线程数将在运行时确定,我必须mData从堆中分配。

我想知道有没有办法不使用堆分配并使用上面的常规数组?

4

2 回答 2

1

每个线程都有自己的堆栈,并且记住堆栈帧在函数返回时被弹出(或可以被认为是弹出)。

这就是为什么我们有“无堆栈 python”,因为 1 个堆栈(python 需要什么)和多个线程不能很好地发挥作用(请参阅全局解释器锁)

您可以将它放在 main 中,这将持续存在,但请记住 C(++) 想在编译时知道所有大小,所以如果线程数发生变化(在编译时不固定),则无法知道这一点。

您真正想要的是不在 main 中的东西,但这不会是模板(在数字中),因为在编译时无法知道该数字。

GCC 提供了一个堆栈分配函数(如 malloc),但我找不到它,但最好避免使用它,因为那时优化确实有效。

同样不要低估您的 CPU 预读能力和 GCC 优化,将数组放在堆上也不错。

有趣的阅​​读好图片,但不幸的是与主题无关: http ://www.nongnu.org/avr-libc/user-manual/malloc.html

于 2013-10-24T11:05:38.300 回答
0

我建议:

std::unordered_map<std::thread::id, T, stackalloc> myTLS;

要么全局锁定所有访问,要么提前准备人口并稍后以只读方式访问。

您可以将它与堆栈分配器结合使用。

typedef short_alloc<pair<const thread::id, T>, maxthrds> stackalloc;

https://howardhinnant.github.io/stack_alloc.html

如果您想要其他解决方案,您可以在此处执行以下操作:

struct Padder
{
    T t;
    char space_[128 - sizeof(T)];  // if sizeof(T) >= 128 just don't include the padding.
};

std::array<Padder, maxthreads> myTLS;

用于 MESI 无瓶颈访问。
使用此方法,您必须关心使用此数组中自己的索引来跟踪线程。

于 2016-06-15T03:25:04.880 回答