基本思想:OpenMP和多线程的互斥锁很像
#pragma omp parallel for
for(int i=0;i<num;i++)
{
#pragma omp critical
//#pragma omp critical(sum)
//#pragma omp critical(i)
sum=sum+i;
}
std::cout<<"sum="<<sum<<std::endl;
}
测试代码 :critical 可以对代码块进行临界区设置,而atomic只能对代码语句进行加持
#include <iostream>
#include <omp.h>
#include<chrono>
using namespace std;
using namespace chrono;
void sequentialProgram(int num)
{
int sum=0;
int doubleI=0;
for(int i=0;i<num;i++)
{
doubleI=i+i;
sum=doubleI+sum;
}
std::cout<<"sum="<<sum<<std::endl;
}
void parallelProgram(int num) {
int sum=0;
int doubleI=0;
#pragma omp parallel for
for(int i=0;i<num;i++)
{
{ doubleI=i+i;
sum=doubleI+sum;}
}
std::cout<<"sum="<<sum<<std::endl;
sum=0;
doubleI=0;
#pragma omp parallel for
for(int i=0;i<num;i++)
{
#pragma omp critical
//#pragma omp critical(sum)
//#pragma omp critical(doubleI)
{ doubleI=i+i; //故意增加一个doubleI变量
sum=doubleI+sum;}
}
std::cout<<"sum="<<sum<<std::endl;
}
int main() {
int num=omp_get_num_procs()*10;//12
auto start_time=std::chrono::steady_clock::now();
sequentialProgram(num);
auto end_time=std::chrono::steady_clock::now();
std::cout<<"sequentialProgram elapse time: "<<std::chrono::duration<double>(end_time-start_time).count()<<" seconds"<<std::endl;
start_time=std::chrono::steady_clock::now();
parallelProgram(num);
end_time=std::chrono::steady_clock::now();
std::cout<<"parallelProgram elapse time: "<<std::chrono::duration<double>(end_time-start_time).count()<<" seconds"<<std::endl;
return 0;
}
测试结果:发现不添加临界区,计算的值并不正确,因此在累加和累乘运算过程中,需要临界区的加持
F:\OpenMP\cmake-build-debug\OpenMP.exe
sum=14280
sequentialProgram elapse time: 0.0004372 seconds
sum=13790
sum=14280
parallelProgram elapse time: 0.0023326 seconds
Process finished with exit code 0
如果将错误的代码注释掉,会发现临界区的执行时间还是长于串行求和的程序的,因此并不划算~ 具体方法参考reduction
F:\OpenMP\cmake-build-debug\OpenMP.exe
sum=14280
sequentialProgram elapse time: 0.0005795 seconds
sum=14280
parallelProgram elapse time: 0.0031314 seconds
Process finished with exit code 0
(2)atomic 对代码语句进行临界设置
atomic 只能针对单条语句线程互斥访问,它的使用和 #pragra omp parallel for 一样 只能直接接语句 不能在套一个大括号
测试代码
#include <iostream>
#include <omp.h>
#include<chrono>
using namespace std;
using namespace chrono;
void sequentialProgram(int num)
{
int sum=0;
int doubleI=0;
for(int i=0;i<num;i++)
{
doubleI=i+i;
sum=doubleI+sum;
}
std::cout<<"sum="<<sum<<std::endl;
}
void parallelProgram(int num) {
int sum=0;
int doubleI=0;
#pragma omp parallel for
for(int i=0;i<num;i++)
{
#pragma omp atomic
sum=i+i+sum;
}
std::cout<<"sum="<<sum<<std::endl;
}
int main() {
int num=omp_get_num_procs()*10;//12
auto start_time=std::chrono::steady_clock::now();
sequentialProgram(num);
auto end_time=std::chrono::steady_clock::now();
std::cout<<"sequentialProgram elapse time: "<<std::chrono::duration<double>(end_time-start_time).count()<<" seconds"<<std::endl;
start_time=std::chrono::steady_clock::now();
parallelProgram(num);
end_time=std::chrono::steady_clock::now();
std::cout<<"parallelProgram elapse time: "<<std::chrono::duration<double>(end_time-start_time).count()<<" seconds"<<std::endl;
return 0;
}
测试结果
F:\OpenMP\cmake-build-debug\OpenMP.exe
sum=14280
sequentialProgram elapse time: 0.0005045 seconds
sum=14280
parallelProgram elapse time: 0.0015284 seconds
Process finished with exit code 0
其中可以使用原子操作的运算符有 +、-、*、/、|、^、&、>>、<<
(3)添加锁
static omp_lock_t m_lock;
omp_init_lock(&m_lock);
#pragma omp parallel for
for(int i=0;i<num;i++)
{
omp_set_lock(&m_lock);
{
....
}
omp_unset_lock(&m_lock);
}
omp_destroy_lock(&m_lock);
测试代码
#include <iostream>
#include <omp.h>
#include<chrono>
using namespace std;
using namespace chrono;
static omp_lock_t m_lock;
void sequentialProgram(int num)
{
int sum=0;
int doubleI=0;
for(int i=0;i<num;i++)
{
doubleI=i+i;
sum=doubleI+sum;
}
std::cout<<"sum="<<sum<<std::endl;
}
void parallelProgram(int num) {
omp_init_lock(&m_lock);
int sum=0;
int doubleI=0;
#pragma omp parallel for
for(int i=0;i<num;i++)
{
omp_set_lock(&m_lock);
doubleI=i+i;
sum=doubleI+sum;
omp_unset_lock(&m_lock);
}
std::cout<<"sum="<<sum<<std::endl;
omp_destroy_lock(&m_lock);
}
int main() {
int num=omp_get_num_procs()*10;//12
auto start_time=std::chrono::steady_clock::now();
sequentialProgram(num);
auto end_time=std::chrono::steady_clock::now();
std::cout<<"sequentialProgram elapse time: "<<std::chrono::duration<double>(end_time-start_time).count()<<" seconds"<<std::endl;
start_time=std::chrono::steady_clock::now();
parallelProgram(num);
end_time=std::chrono::steady_clock::now();
std::cout<<"parallelProgram elapse time: "<<std::chrono::duration<double>(end_time-start_time).count()<<" seconds"<<std::endl;
return 0;
}
测试结果 如果计算量很大的话,这样写会消耗的时间高于串行程序
F:\OpenMP\cmake-build-debug\OpenMP.exe标签:std,doubleI,int,lock,sum,omp,critical,time From: https://blog.51cto.com/u_12504263/5719058
sum=14280
sequentialProgram elapse time: 0.0341926 seconds
sum=14280
parallelProgram elapse time: 0.0020649 seconds
Process finished with exit code 0