C++ OpenMP 任务 - 通过引用传递问题
C++ OpenMP Tasks - passing by reference issue
我目前在一个系统上工作,我在其中读取超过 2 亿条记录(行)的文件,因此我正在缓冲记录并使用 OpenMP 任务来管理每个批次,同时继续处理输入。缓冲区中的每条记录在 work_on_data
中大约需要 60μ 来处理,并将生成一个字符串结果。为了避免关键区域,我为结果创建了一个向量,并通过地址将记录占位符(我插入该向量)传递给 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
都不会是空字符串(如初始化的那样)。 但是,当合并结果时,每个结果仍然是一个空字符串。关于scoping/addressing,我可能在这里做了一些愚蠢的事情,但我不明白问题是什么。有什么想法吗?
提前致谢。
将某物推入矢量会导致在矢量内构建它的副本。因此,您的 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
介于两者之间,线程将是处理相同的数据。
我目前在一个系统上工作,我在其中读取超过 2 亿条记录(行)的文件,因此我正在缓冲记录并使用 OpenMP 任务来管理每个批次,同时继续处理输入。缓冲区中的每条记录在 work_on_data
中大约需要 60μ 来处理,并将生成一个字符串结果。为了避免关键区域,我为结果创建了一个向量,并通过地址将记录占位符(我插入该向量)传递给 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
都不会是空字符串(如初始化的那样)。 但是,当合并结果时,每个结果仍然是一个空字符串。关于scoping/addressing,我可能在这里做了一些愚蠢的事情,但我不明白问题是什么。有什么想法吗?
提前致谢。
将某物推入矢量会导致在矢量内构建它的副本。因此,您的 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
介于两者之间,线程将是处理相同的数据。