对相关数据执行任务级并行性

Performing task level parallelism with dependent data

本文关键字:并行性 执行任务 数据      更新时间:2023-10-16

我有visual studio,其中不支持openMP 3.0(这意味着它没有任务构造)问题是一个线程必须生成多组数据数组,另一个线程必须为每个完成的集合处理该数据数组…在不使用任务的情况下,有什么解决办法吗?如果我能得到任何帮助,我将不胜感激。代码:

    int id = omp_get_thread_num();
    if (id == 0)
    {
        for (int k = 0; k < n; k++)
        {
            int f = k * r * c;
            for (int i = 0; i < r; i++)
            {
                int rw = i * c;
                for (int j = 0; j < c; j++)
                {
                    p[f + rw + j] = rand() % 65535;
                }
            }
            _sleep(500);
        }
    }
    if (id == 1)
    {
        _sleep(200);
        for (int k = 0; k < n; k++)
        {
            int f = k * r* c;
            cout << "n" << k;
            for (int i = 0; i < r; i++)
            {
                int rw = i * c;
                for (int j = 0; j < c; j++)
                {
                    p[f + rw + j] *= sin(2 * 3.14 * (10.0 / 100.0) * k);
                }
            }
            Mat img(r, c, CV_16UC1, p);
            namedWindow("output", CV_WINDOW_AUTOSIZE);
            imshow("output", img);
            waitKey();
        }
    }
}
system("pause");

这个程序工作,但我不知道它是否在并行或串行运行或任何冗余发生…

是的,有标准的c++ 11线程,但是需要做一些工作。

线程的使用/代码的基本结构:

我假设你是using namespace std;。此外,您还需要:

#include <thread>
#include <chrono>
技巧是把你的线程代码放在一个void函数中,接受你的线程id作为输入,以及共享变量(通过引用)。例如,我将此用于快速可行性测试(您必须微调/调整类型等):
void mytask (int id, int&n, int& r, int& c, double *p)
{
    if (id == 0)
    { ... }
    if (id == 1)
    { ... }
}

你还必须使用正确的睡眠功能来替换你以前的功能:

    this_thread::sleep_for (std::chrono::milliseconds(500));  //_sleep (500);
在你的代码中,你可以在声明和初始化共享变量之后启动你的线程:
...
thread t1 (mytask, 0, n, r, c, p );  // create an launch threads
thread t2 (mytask, 1, n, r, c ,p );  // 
t1.join();   // wait for t1 to finish
t2.join();   // wait for t2 to finish 
...

这是基本概念。它与VC2013 express一起工作,没有openMP,至少在概念上是这样。

共享数据和同步:

现在,您还必须微调并检查两个线程之间是否在相同的变量上存在竞争,并且可能使用or来序列化访问。

对算法的分析表明,第一个线程将随机数放入表中,第二个线程对这些结果应用公式。这假设第一个线程总是在第二个线程使用它们之前计算元素。但是,您不能对线程的调度做过多的假设。系统可以使其中一个慢下来,甚至冻结其中一个,稍后再恢复。

这里有一个初步的想法(但需要进一步阐述),使用:
#include <atomic>

定义一个共享的受保护变量来存储外部循环计数器(我在这里建议这样做,因为两个线程使用相同的顺序访问p[]):

atomic<int> line_ready=-1;  // U used here a global variable

在生产线程中,在外循环的末尾添加一行:

line_ready.store (k);    // sync: loop was processed from 0 to k. 

在消费线程中,在外部循环的开始处添加以下行:

while (k>line_ready.load()) // sync: read k to know if we have to wait for data
this_thread::sleep_for (std::chrono::milliseconds(100)); // wait 

如果数据不可用,这将等待数据。现在就看你的了!