使用从属数据执行任务级并行

时间:2014-06-18 06:25:54

标签: c++ multithreading task

我有视觉工作室,其中没有支持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");

这个程序有效,但我不知道它是并行运行还是串行运行,或者是否发生任何冗余......

1 个答案:

答案 0 :(得分:2)

是的,有标准的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 
...

这是基本概念。它适用于没有openMP的VC2013 express,至少对于概念而言。

共享数据和同步:

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

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

所以这是一个初步想法(但需要进一步阐述),使用:

#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 

如果数据不可用,它将等待数据。现在它取决于你!