OpenMP - 在循环中使用并行调用函数,使用Mat对象

时间:2018-05-01 21:02:13

标签: c++ multithreading

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

这是函数更改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..

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

但至于我的问题:row我需要一个确切的colascii个数字。我看到花时间的差异,我真的很想看0.17..。但是..如果我清楚地理解,当我使用parallel for时:它创建了几个线程,迭代的每个部分都适用于几个线程的每个线程。好的。 但是我无法理解,为什么它只适用于the first iteration而其他人不能继续改变位?

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

你能帮忙吗?我能以正确的方式使用parallel for吗?

1 个答案:

答案 0 :(得分:1)

由于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.