C ++ OpenMP任务 - 通过引用问题传递

时间:2015-01-08 21:32:24

标签: c++ reference io parallel-processing openmp

我目前正在开发一个系统,我在这个系统中读取超过2亿条记录(行)的文件,因此我正在缓冲记录并使用OpenMP任务来管理每个批处理,同时继续处理输入。缓冲区中的每条记录大约需要60μ才能在work_on_data中处理,并生成字符串结果。为了避免关键区域,我为结果创建了一个向量,并通过地址将记录占位符(我插入到此向量中)传递给work_on_data函数:

int i = 0;
string buffer[MAX_SIZE];
vector<string> task_results;

#pragma omp parallel shared(map_a, task_results), num_threads(X) 
#pragma omp single
{
    while (getline(fin, line) && !fin.eof())
    {
        buffer[i] = line;
        if (++i == MAX_SIZE)
        {
            string result = "";
            task_results.push_back(result);
#pragma omp task firstprivate(buffer)
            work_on_data(buffer, map_a, result);
            i = 0;
        }
    }
}

// eventually merge records in task_results

work_on_data结束时,传入的每个result都不是空字符串(初始化)。 然而,当合并结果时,每个结果仍然是一个空字符串。我可能在这里做了一些关于作用域/寻址的蠢事,但我不知道问题是什么。有什么想法吗?

提前致谢。

1 个答案:

答案 0 :(得分:2)

将某个东西推入向量会导致它的副本在向量中构建。所以你的work_on_data函数不能获得对向量内部字符串的引用,而是对if块内的字符串的引用。要解决此问题,您可以重写代码以使其能够访问push_back之后的最后一个元素,如下所示:

if (++i == MAX_SIZE)
{
    task_results.push_back("");
#pragma omp task firstprivate(buffer)
    work_on_data(buffer, map_a, task_results.back());
    i = 0;
}

修改

我忘记了向量重新分配时迭代器失效,另外对back()的调用会导致竞争条件。使用(智能)指针(如评论所暗示的)和专用计数器,这对我来说没有任何段错误:

vector<shared_ptr<string>> task_results;

int ctr = 0
...
if (++i == MAX_SIZE) {
    task_results.push_back(make_shared<string>());
#pragma omp task firstprivate(buffer, ctr) 
    work_on_data(buffer, map_a, *task_results.back[ctr]);
    i = 0;
    ++ctr;

}

我认为back()版本会出现段错误,因为该函数同时被许多不同的线程调用,如果主线程也在两者之间的某个地方设置push_back,那么线程就会在相同的数据。