首页 > 解决方案 > OpenMP - 在循环中使用并行调用函数,使用 Mat 对象

问题描述

我有一个文本(关于136.000字符),我想把它们写在图片中。我的文本存储在 中vector,这意味着我可以使用循环for来更改low bit像素的 a。

这是功能更改last bit

int changeLastChar(int value, int newEnd) {
    // change last decimal of an integer
    if (newEnd > 9) return 1;
    value /= 10;
    value *= 10;
    value += newEnd;
    return value;
}

这是在一张图片里写的:

void writeTextToImage3(Mat& image, std::vector<char> message, int count) {
    // write text to pixels by changing the last decimal in every RGB value
    int ascii;
    int row;
    int col;


#pragma omp parallel 
    {
        #pragma omp for
        for (int i = 0; i < message.size(); i++)
        {

            row = count/ image.cols;
            col = count % image.cols;

            ascii = message[i];
            count++;


            image.at<Vec3b>(row, col)[0] = changeLastChar(image.at<Vec3b>(row, col)[0], ascii % 10);    // blue

            ascii /= 10;
            image.at<Vec3b>(row, col)[1] = changeLastChar(image.at<Vec3b>(row, col)[1], ascii % 10);    // green

            ascii /= 10;
            image.at<Vec3b>(row, col)[2] = changeLastChar(image.at<Vec3b>(row, col)[2], ascii % 10);    // red                                                                                                                                                          
        }

    }
}

我可以给出一些结果,如果我使用函数without OpenMP,它需要:0.29..

With OpenMP使用#pragma omp for0.26..

With OpenMP使用#pragma omp parallel for0.17..

for我知道and之间的区别parallel for,如果我使用 just for,我只有一个主线程,而不是一个组。

但至于我的问题:row我需要col每个ascii. 我看到了花时间的不同,我真的很喜欢看到0.17..。但是..如果我清楚地理解,当我使用parallel for: 它会创建多个线程,并且迭代的每个部分都适用于多个线程的每个线程。好的。但我不明白,为什么它只适用于the first iteration而其他人不能继续改变位?

我的想法是:当某个部分(不是第一个,一些..)正在工作时,它计算一个变量cout++,它计算row and col. 当然,它从 开始计数0,但我需要从 计数THE FIRST THREAD0而不是某个部分。这就是为什么如果我不使用parallel,它会按照正确的顺序排列,因为它有一个主线程。

你能帮我吗?我可以parallel for正确使用吗?

标签: c++multithreading

解决方案


由于count在所有线程之间共享,因此您会得到一个竞争条件,因为它是在每个循环中写入的。您还可以获得局部变量的竞争条件,这些变量应该在循环内而不是在循环外声明(这样每个线程都有自己的副本)。

你已经有了i这个增量count,所以你可以使用它。不要修改count,更改您的rowcol计算以count使用i

int row = (count + i) / image.cols;
int col = (count + i) % image.cols;
int ascii = message[i];

您也可以只调用image.at<Vec3b>(row, col)一次,将该结果存储在一个变量中,然后使用它:

auto &v = image.at<Vec3b>(row, col);

v[0] = changeLastChar(v[0], ascii % 10);
// etc.

推荐阅读