日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

openmp 互斥锁 mysql_openMP 函数总结(并行程序设计导论)

發(fā)布時(shí)間:2024/9/19 数据库 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 openmp 互斥锁 mysql_openMP 函数总结(并行程序设计导论) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本篇文章只是記錄api的用法和回顧,方便記憶

openMP

openMP提供“基于指令”的共享內(nèi)存API。這就意味著在c和c++中,有一些特殊的預(yù)處理指令pragma。在系統(tǒng)中加入預(yù)處理指令一般時(shí)用來(lái)允許不是基本C語(yǔ)言的規(guī)范的行為。

不支持pragma的編譯器會(huì)忽略pragma指令提示的那些語(yǔ)句,這樣就允許使用pragma的程序在不支持它的平臺(tái)上運(yùn)行。

OpenMP的pragma總是以 ##pragma omp 開(kāi)始

簡(jiǎn)單例子

#include

#include

#include

void Hello(void);

int main(int argc,char* argv[])

{

/*

long strtol(

const char* number_p *in*, 第一個(gè)參數(shù)是字符串

const char** end_p *out*,終止的非法字符串

int base *in* 進(jìn)制(2-36)

)

例:

char buffer[20]="10379cend$3";

char *stop;

printf("%d\n",strtol(buffer, &stop, 2));

printf("%s\n", stop);

輸出結(jié)果:

2

379cend$3

*/

int thread_count = strtol(argv[1],NULL,10);

#pragma omp parallel num_threads(thread_count)

Hello();

return 0;

}

void Hello(void)

{

int my_rank = omp_get_thread_num();

int thread_count = omp_get_num_threads();

printf("hello from thread %d of %d \n",my_rank,thread_count);

}

#編譯

gcc -g -Wall -fopenmp -o main main.c

#-g :產(chǎn)生供gdb調(diào)試用的可執(zhí)行文件

# http://www.jianshu.com/p/30ffc01380a0

#-Wall:編譯后顯示所有警告

#-fopenmp 使用mpi支持

#-o:輸出到指定文件

#pragma omp pallel

使用parallel是用來(lái)表明之后的結(jié)構(gòu)化代碼塊(一個(gè)結(jié)構(gòu)化代碼塊時(shí)一條C語(yǔ)句或者只有一個(gè)入口和一個(gè)出口的一組復(fù)合C語(yǔ)句)應(yīng)該被多個(gè)線程并行執(zhí)行。

完成代碼塊前會(huì)有一個(gè)隱式路障,先完成的線程必須等待線程組其他線程完成代碼塊。

- num_threads 子句

允許程序員指定執(zhí)行后代碼塊的線程數(shù)

程序可以啟動(dòng)的線程數(shù)可能會(huì)受系統(tǒng)定義的限制。OpenMP標(biāo)準(zhǔn)并不保證實(shí)際能夠啟動(dòng)thread_count個(gè)線程。

#pragma omp parallel num_threads(thread_count)

線程被同一個(gè)進(jìn)程派生,這些線程共享大部分資源。有它自己的棧和計(jì)數(shù)器。當(dāng)一個(gè)線程完成了執(zhí)行,它就又合并到啟動(dòng)它的線程中。

每個(gè)線程都有它自己的棧,所以執(zhí)行一個(gè)代碼塊將在代碼塊內(nèi)創(chuàng)建自己的私有局部變量。

-func omp_get_thread_num | omp_get_num_threads

#獲得當(dāng)前線程的編號(hào)

int omp_get_thread_num(void)

#獲得線程數(shù)量

int omp_get_num_threads(void)

錯(cuò)誤檢查

可以通過(guò)預(yù)處理宏_OPENMP是否定義。

#ifdef _OPENMP

#include

#endif

#ifdef _OPENMP

int my_rank=omp_get_thread_num();

int thread_count=omp_get_num_threads();

#else

int my_rank=0;

int thread_count=1;

#endif

#pragma omp critical

只有一個(gè)線程能夠執(zhí)行對(duì)應(yīng)代碼塊,并且第一個(gè)線程完成操作前,沒(méi)有其他的線程能夠開(kāi)始執(zhí)行這段代碼。

當(dāng)不添加name時(shí),OpenMP默認(rèn)做法將所有臨界區(qū)代碼塊作為符合臨界區(qū)一部分,添加name后兩個(gè)不同名字的cirtical指令保護(hù)的代碼可以同時(shí)執(zhí)行。

語(yǔ)法

#pragma omp critical [(name)]

用法

#pragma omp critical

global_result += my_result;

變量的作用域

在parallel塊之前被聲明的變量的缺省作用域時(shí)共享的。

在parallel指令前已經(jīng)被聲明的變量,擁有線程組中所有線程間的共享作用域,而在塊中聲明的變量(例如,函數(shù)中的變量)中有私有作用域。

- reduction 規(guī)約子句

語(yǔ)法

reduction(:)

# operator : +,*,-,&,|,^,&&,||

用法

當(dāng)一個(gè)變量包含在一個(gè)reduction子句中時(shí),變量本身是共享的。然而,線程組中的每個(gè)線程都創(chuàng)建自己的私有變量。在parallel塊里,每當(dāng)一個(gè)線程執(zhí)行涉及這個(gè)變量(共享變量)的語(yǔ)句時(shí),它使用的其實(shí)時(shí)私有變量。當(dāng)parallel塊執(zhí)行結(jié)束后,私有變量中的值被整合到一個(gè)共享變量中。

如果一個(gè)規(guī)約變量時(shí)float或double變量型數(shù)據(jù),那么當(dāng)使用不同數(shù)量的線程時(shí),結(jié)果可能有些許不同。這是由于浮點(diǎn)數(shù)運(yùn)算不滿足結(jié)合律

OpenMp會(huì)為此創(chuàng)建一個(gè)臨界區(qū),并且在這個(gè)臨界區(qū)中,將存儲(chǔ)在私有變量中的值進(jìn)行相加(或其他operator)。

global_result=0.0;

#pragma omp parallel num_threads(thread_count) reduction(+:global_result)

global_result += Local_trap(double a,double b,int n);

####等同

global_result=0.0;

#pragma omp parallel num_threads(thread_count)

{

double my_result =0.0;/*私有變量*/

my_result += Local_trap(double a,double b,int n);

#pragma omp critial

global_result += Local_trap(double a,double b,int n);

}

#pragma omp parallel for

parallel for 指令生成一組線程來(lái)執(zhí)行后面的結(jié)構(gòu)化代碼塊(必須是for循環(huán))。

系統(tǒng)通過(guò)在線程間劃分循環(huán)迭代來(lái)并行化for循環(huán)。與parallel指令非常不同,因?yàn)樵趐arallel指令之前的塊,一般來(lái)說(shuō)其工作必須由線程本身在線程之間劃分。

在一個(gè)已經(jīng)被parallel for指令并行化的for循環(huán)中,線程間的缺省劃分方式由系統(tǒng)決定(大約 m(迭代次數(shù))/thread_count)。

在一個(gè)被parallel for指令并行化的循環(huán)中,循環(huán)變量的缺省作用域是私有的,每個(gè)線程會(huì)有它自己的循環(huán)變量的副本。

合法方式

h=(b-a)/n;

approx =(f(a)+f(b))/2.0;

# pragma omp parallel for num_threads(thread_count) reduction(+:=approx)

approx += f(a+i*h);

approx = h* approx;

線程重用

與parallel指令不同的是,for指令并不創(chuàng)建任何線程。它使用已經(jīng)在parallel塊中創(chuàng)建的線程。在循環(huán)的末尾有一個(gè)隱式的路障。

#pragma omp parallel num_threads(thread_count) default(none) \

shared(a,n) private(i,tmp,phase)

for(phase = 0;phase

{

if(phase%2 == 0)

#pargma omp for

for(i=1;i

...

else

#pargma omp for

for(i=1;i

...

}

數(shù)據(jù)依賴性

OpenMP編譯器不檢查parallel for指令并行化的循環(huán)所包含的迭代間的依賴關(guān)系,而是由程序員來(lái)識(shí)別這些依賴。

一個(gè)或更多個(gè)迭代結(jié)果依賴于其他迭代的循環(huán),一般不能被OpenMP正確地并行化。

數(shù)據(jù)依賴

#y依賴于x

for(i=0;i

{

x[i]=a+i*h;

y[i]=exp(x[i]);

}

循環(huán)依賴

一個(gè)值在循環(huán)中計(jì)算,其結(jié)果在之后迭代中使用。

#并行化后某一個(gè)邊界值將是另一個(gè)并行化線程中的使用。

fibo[0]=fibo[1]=1;

for(i=2;i

fibo[i]=fibo[i-1]+fibo[i-2];

- private 子句

在private子句列舉的變量,在每個(gè)線程上都有一個(gè)私有副本被創(chuàng)建。

一個(gè)私有作用域的變量的值在parallel塊或者parallel for塊的開(kāi)始處是未指定的。它的值在parallel塊或者parallel for塊完成之后也是未指定的。

#include

#include

#include

void Hello(void);

int main(int argc,char* argv[])

{

int x=5;

#pragma omp parallel private(x)

{

int my_rank =omp_get_thread_num();

printf("Thread %d > before initialization,x=%d \n",my_rank,x);

x=2*my_rank+2;

printf("Thread %d > after initialization,x=%d \n",my_rank,x);

}

printf("after parallel,x=%d \n",x);

return 0;

}

- default(none) 子句

讓程序員明確塊中每個(gè)變量的作用域。

double sum = 0.0;

/*

sum是一個(gè)規(guī)約變量(同時(shí)擁有私有和共享作用域的屬性)。

*/

#pragma omp parallel for num_threads(thread_count) \

default(none) redcution(+:sum) private(k,factor) \

shared(n)

for(k=0;k

if(k%2 ==0)

factor = 1.0;

else

factor = -1.0;

sum += factor/(2*K+1);

- schedule子句

對(duì)線程進(jìn)行調(diào)度。

語(yǔ)法

schedule( [,]

type可以時(shí)一下的任意一個(gè)。

static。迭代能夠在循環(huán)執(zhí)行前分配給線程。

(static,1)

Thread0:0,3,6,9

Thread1:1,4,7,10

Thread2:2,5,8,11

(static,2)

Thread0:0,1,6,7

Thread1:2,3,8,9

Thread2:4,5,10,11

缺省調(diào)度(static,total_iterations/thread_count)

dynamic或guided。迭代在循環(huán)執(zhí)行時(shí)被分配給線程,因此在一個(gè)線程完成了它的當(dāng)前迭代集合后,他能從運(yùn)行時(shí)系統(tǒng)中請(qǐng)求更多。

dynamic調(diào)度中,迭代也被分成chunksize個(gè)連續(xù)迭代的塊。

每個(gè)線程執(zhí)行一塊,并且當(dāng)一個(gè)線程完成一塊時(shí),

他將從運(yùn)行時(shí)系統(tǒng)請(qǐng)求另一塊,直到所有的迭代完成。

chunksize可以被忽略。當(dāng)它被忽略時(shí),chunksize為1。

在guided調(diào)度中,每個(gè)線程也執(zhí)行一塊,并且當(dāng)一個(gè)線程完成一塊,將請(qǐng)求另一塊。

然而,在guided調(diào)度中,當(dāng)塊完成后,新塊的大小變小。

例如:

n=10 000并且thread_count=2時(shí),迭代將如表那樣分配。塊的大小近似等于的迭代數(shù)除以線程數(shù)。第一塊的大小為9999/2 ~=5000,因?yàn)?999個(gè)未被分配的迭代。第二塊的大小為4999/2~=2500。以此類推。

| 線程 | 塊 | 快的大小 | 剩下的迭代代數(shù) |

| 0 | 1~5000 | 5000 | 4999 |

| 1 | 5001-7500| 2500 | 2499 |

| 1 | 7501-8750| 1250 | 1249 |

...

auto。編譯器和運(yùn)行時(shí)系統(tǒng)決定調(diào)度方式。

runtime。調(diào)度在運(yùn)行時(shí)決定。

chunksize是一個(gè)正整數(shù)。在OpenMP中,迭代塊在順序循環(huán)中連續(xù)執(zhí)行的一塊迭代語(yǔ)句,塊中的迭代次數(shù)時(shí)chunsize。只有static,dynamic和guided調(diào)度有chunksize。

設(shè)置環(huán)境變量

$export OMP_SCHEDULE="static,1"

#pragma omp barrier

顯式的路障,當(dāng)所有的線程都到達(dá)了這個(gè)路障時(shí),這些線程就可以接著往下執(zhí)行。

#pragma omp atomic

只能保護(hù)由一條C語(yǔ)言賦值語(yǔ)句所形成的臨界區(qū),是一個(gè)更高效的指令。

語(yǔ)句必須是以下形式:

#op:+,*,-,/,&,^,|,<> .

#expreesion不能引用x。

x=;

x++;

++x;

x--;

y--;

用法

#其他線程對(duì)x的更新必須等到該線程對(duì)x的更新結(jié)束之后。

#但對(duì)y不受保護(hù),因此程序的結(jié)果是不可預(yù)測(cè)的。

#pragma omp atomic

x+=y++

簡(jiǎn)單鎖

第一個(gè)函數(shù)初始化鎖,所以鎖此時(shí)處于解鎖狀態(tài)。

第二個(gè)函數(shù)嘗試獲得鎖,如果成功,調(diào)用該函數(shù)的線程可以繼續(xù)執(zhí)行,如果失敗調(diào)用該函數(shù)的線程被阻塞,直到鎖被其他線程釋放。

第三個(gè)函數(shù)釋放鎖,以便其他線程獲得該鎖。

第四個(gè)函數(shù)銷貨鎖。

void omp_init_lock(omp_lock_t* lock_p /*out*/);

void omp_set_lock(omp_lock_t* lock_p /*in/out*/);

void omp_unset_lock(omp_lock_t* lock_p /*in/out*/);

void omp_destroy_lock(omp_lock_t* lock_p /*in/out*/);

用法

static omp_lock_t lock;

void test11()

{

omp_init_lock(&lock); // 初始化互斥鎖

#pragma omp parallel for

for (int i = 0; i < 5; ++i)

{

omp_set_lock(&lock); //獲得互斥器

std::cout << omp_get_thread_num() << "+" << std::endl;

std::cout << omp_get_thread_num() << "-" << std::endl;

omp_unset_lock(&lock); //釋放互斥器

}

omp_destroy_lock(&lock); //銷毀互斥器

}

#pragma omp single

這樣做能確保接下來(lái)的結(jié)構(gòu)化代碼塊由線程組中的一個(gè)線程執(zhí)行,而組內(nèi)其他線程等待直到該線程執(zhí)行結(jié)束(在代碼塊的最后設(shè)置一個(gè)隱式路障)

#include

#include

#include

int main()

{

#pragma omp parallel

{

int my_rank = omp_get_thread_num();

if(my_rank == 1)

{

int x=1;

while(x<1e9)

{

x+=1;

}

}

#pragma omp single

printf("%d \n",my_rank);

printf("----> %d \n",my_rank);

}

return 0;

}

#pragma omp master

這樣能確保線程0執(zhí)行接下來(lái)的結(jié)構(gòu)化代碼塊。然后master指令在最后不會(huì)設(shè)置隱式路障。

-func omp_get_wtime

獲取運(yùn)行時(shí)間。

總結(jié)

以上是生活随笔為你收集整理的openmp 互斥锁 mysql_openMP 函数总结(并行程序设计导论)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。