代码之家  ›  专栏  ›  技术社区  ›  Lorah Attkins

重置OpenMP中的线程局部变量

  •  4
  • Lorah Attkins  · 技术社区  · 7 年前

    我需要一种一致的方法来重置程序创建的所有线程局部变量。问题在于线程本地数据是在不同的地方创建的,而不是在使用它们的地方。

    我的课程大纲如下:

    struct data_t { /* ... */ };
    
    // 1. Function that fetches the "global" thread-local data
    data_t& GetData()
    {
        static data_t *d = NULL;
        #pragma omp threadprivate(d); // !!!
    
        if (!d) { d = new data_t(); }
    
        return *d;
    }
    
    // 2 example function that uses the data
    void user(int *elements, int num, int *output)
    {
        #pragma omp parallel for shared(elements, output) if (num > 1000)
        for (int i = 0; i < num; ++i)
        {
            // computation is a heavy calculation, on memoized data
            computation(GetData()); 
        }
    }
    

    现在,我的问题是我需要一个重置数据的函数,即必须考虑创建的每个线程本地对象。

    目前,我的解决方案是使用一个并行区域,希望它使用的线程数与“parallel For”相等或更多,因此每个对象都可以“迭代”通过:

    void ClearThreadLocalData()
    {
        #pragma omp parallel
        {
            // assuming data_t has a "clear()" method
            GetData().clear();
        }
    }
    

    是否有更惯用/安全的方法来实现 ClearThreadLocalData() ?

    1 回复  |  直到 7 年前
        1
  •  2
  •   1201ProgramAlarm    7 年前

    您可以为数据创建和使用全局版本号。每次需要清除现有缓存时,都将其递增。然后修改 GetData 若存在现有数据对象,请检查版本号;若现有数据对象已过期,则丢弃现有数据对象并创建新数据对象。(分配的 data_t 对象可以存储在 数据\u t 如果可以修改该类,或者在第二个线程中修改局部变量(如果不可以)你会得到这样的结果

    static int dataVersion;
    
    data_t& GetData()
    {
        static data_t *d = NULL;
        #pragma omp threadprivate(d); // !!!
    
        if (d && d->myDataVersion != dataVersion) {
            delete d;
            d = nullptr;
        }
        if (!d) { 
            d = new data_t();
            d->myDataVersion = dataVersion;
        }
    
        return *d;
    }
    

    这并不取决于 Clear 中的方法 数据\u t ,但如果有,请将删除和重置替换为调用 清楚的 .我正在使用 d = nullptr 避免重复调用 new data_t()

    全球 dataVersion 可能是的静态成员 数据\u t 如果要避免使用全局变量,如果需要,它可以是原子变量 获取数据 需要改变才能解决这个问题。

    当需要重置数据时,只需更改全局版本号:

    ++dataVersion;