首页 > 其他分享 >4、OpenMP的临界区critical、atomic、omp_lock_t

4、OpenMP的临界区critical、atomic、omp_lock_t

时间:2022-09-28 11:39:31浏览次数:36  
标签:std doubleI int lock sum omp critical time


基本思想: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
sum=14280
sequentialProgram elapse time: 0.0341926 seconds
sum=14280
parallelProgram elapse time: 0.0020649 seconds

Process finished with exit code 0

标签:std,doubleI,int,lock,sum,omp,critical,time
From: https://blog.51cto.com/u_12504263/5719058

相关文章