1 / 30

البرمجة التفرعية

البرمجة التفرعية . الجلسة الثالثة. Collective Communication توابع الاتصال الجماعية. بالإضافة إلى توابع الاتصال من النمط Point- To_Point السابقة ( Send, Receive )، تقدم الـ MPI مجموعة أخرى من توابع الاتصالات الجماعية Collective Communication .

asis
Télécharger la présentation

البرمجة التفرعية

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. البرمجة التفرعية الجلسة الثالثة Eng. ramimahfoud http://irami.im

  2. Collective Communicationتوابع الاتصال الجماعية • بالإضافة إلى توابع الاتصال من النمط Point-To_Point السابقة (Send, Receive)، تقدم الـMPI مجموعة أخرى من توابع الاتصالات الجماعية Collective Communication. • هذه المجموعات تسمح بعمل سلسلة من توابع الاتصال point-to point في تعليمة واحدة • الاتصال الجماعي غالبا ما يشترك فيه كل ال Processes الموجودة في بئية الاتصال communicatio . • من أجل كل process ينتهي استدعاء التابع عندما تتم عملية نقل البيانات • إدراة ال tag في توابع الاتصال هذه تتم بشكل شفاف وداخلي ضمن التوابع ولا داعي لتعريفها ضمن التابع

  3. أنواع توابع الاتصال الجماعي • هناك ثلاثة أصناف من توابع الاتصال الجماعي : • ❶التوابع التي تضمن التزامن العام (global synchronizations) : MPI_Barrier() • ❷ التوابع التي تقوم بنقل البيانات بين الإجرائات : • التوزيع العام للبيانات MPI_Bcast() • التوزيع المحدد للبيانات أي تقسيم البيانات على الإجرائيات (Process ) : MPI_Scatter( ) • تجميع البيانات الموزعة : MPI_Gather( ) • التجميع بواسطة جميع الإجراءات التي تحوي البيانات الموزعة أي التجميع ضمن جميع الإجرائيات :MPI_Allgather() • توزيع محدد بواسطة جميع الاجرائات التي تحوي بيانات مخصصة أي كل إجرائية تقوم بعمليه توزيع للكل : MPI_Alltotal() • ❸ التوابع التي بالأضافة إلى إدارة الاتصالات تقوم بتنقيذ عمليات على البيانات التي تنقل وهي : • توابع الاخترال ( التخفيض ) (reduction operations ) مثل ( الجمع – الضرب – القيمة العظمى – القيمة الصغرى و غيرها من العمليات القياسية أو القيام بعمليات يعرفها المستخدم ) والتابع هو : MPI_Reduce() • تابع يقوم بالأضافة إلى الاخترال بإرسال القيمة الناتجة إلى كل الإجرائيات process أي هو فعليا • MPI_Reduce() ثم MPI_Bcast() والتابع هو MPI_Allreduce()

  4. Broadcast البث العام • ابسط أنواع توابع مجموعات الاتصال هو البث العام (Broadcast ). في البث العام (Broadcast ) تقوم Process وحيدة بإرسال نسخة من نفس البيانات إلى كل ال Processes في مجال الاتصال .الصورة التالية توضح العملية . التابع الذي يحقق البث العم في ال MPI هو MPI_Bcast( ) .

  5. Broadcast البث العام • حيث أننا نلاحظ انه بعد استدعاء التابع في الاجرائية رقم 2 تصبح القيمة A موجودة في جميع ال (Processes)

  6. Broadcast البث العام • الصيغة العامة للتابع MPI_Bcast() intMPI_Bcast(void *buf, / **** in / out ****/ int count, / *** in ***/ MPI_Datatypedatatypem , /**** in ****/ int root, /***** in ****/ MPI_Commcomm /**** in ****/) • buf : موقع الذاكرة لبداية عناصر الرسالة المرسلة • coun: عدد عناصر الرسالة • datatypem: نمط بيانات عناصر الرسالة • root: رتبة الإجرائية الجذر • comm : بنية لااتصال

  7. Broadcast البث العام • الصيغة العامة للتابع MPI_Bcast() intMPI_Bcast(void *buf, int count, MPI_Datatype ,datatypemint root, MPI_Commcomm) يقوم هذا التابع بإرسال البيانات الموجودة في الـbuffer على الـprocess ذات الـrank المساوي للـroot في الـcommunicator إلى كل إجرائية processفي ذلك الـcommunicator . ولا يتم الاستقبال هنا بواسطة الإجراء MPI_Recv، وإنما عن طريق استدعاء الروتين MPI_Bcast نفسه وبنفس قيم البارامترات، وعندها تتم معرفة العملية المرسلة من المستقبلة بواسطة مقارنة قيمة الـrank للعملية التي تنفذ مع البارامتر root فإذا كانا متساويين تكون العملية في حالة إرسال، وفيما عدا ذلك تكون في حالة استقبال. يعد استخدام روتين البث الجماعي أكثر سرعة وفعالية من حيث اختزال النص البرمجي، ومن حيث الزمن المستغرق في عملية الاتصال. كمثال على استخدام الإجراء السابق، بفرض لدينا مجموعة من الحواسيب مربوطة بشبكة، كل من هذه الحواسيب تنفذ نفس العملية، ستتولى عملية رئيسية توزيع المدخلات على العمليات الأخرى التي ستقوم بإنجاز العمل المطلوب.

  8. Broadcast البث العام • مثال : البرنامج يقوم بتوليد مصفوفة من 5 أعداد عشوائية بين 0 و 999 في العقدة رقم ( 0 )ثم يتم توزيع هذه المصفوفة على جميع الإجرائيات في بيئة الاتصال مع طباعة المصفوفة المستقبلة في كل إجرائية

  9. #include<iostream> #include<mpi.h> using namespace std; void main(intargc, char** argv) { intmynode,totalnodes; MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD,&totalnodes); MPI_Comm_rank(MPI_COMM_WORLD,&mynode); int a[5]; cout<<"my rank is:"<<mynode<<endl; if(mynode==0){ for(inti=0;i<5;i++){ a[i]=rand()%1000; } } cout<<"before Bcast a is "<<endl; for(inti=0;i<5;i++){ cout<<a[i]<<" "; } MPI_Bcast(a,5,MPI_INT,0,MPI_COMM_WORLD); cout<<endl<<"after Bcast a is "<<endl; for(inti=0;i<5;i++){ cout<<a[i]<<" "; } cout<<endl; system("pause"); MPI_Finalize(); }

  10. Scatterالبعثرة • ترسل بيانات مختلفة من ال process الجذر نحو ال processes الأخرى والتابع الذي يحقق هذا الشئ في ال MPIهو MPI_Scatter () وهي فعليا عملية تقسيم البيانات من ال process الجذر نحو جميع ال processes

  11. Scatterالبعثرة intMPI_Scatter( void* send_buffer, intsend_count, MPI_Datatypesend_type, void* received_buffer, intreceive_count, MPI_Datatypereceive_type, int root, MPI_Commcomm) عند استدعاء الإجراء السابق، تقوم الـProcess ذات الرتبة root بتوزيع محتويات ال ـsend_buffer بين العمليات. حيث يتم إرسال send_count عنصر إلى كل عملية (يجب أن يكون الـ send_count عدد صحيح موجب). ونشير هنا إلى أن السطر الأول من البارامترات ذو أهمية فقط من جهة الـ root.تقوم كل عملية من العمليات الموجودة في مجال الاتصال المحدد (comm) باستقبال حصتها (المقدرة بـ receive_count) من المعطيات وتخزينها في الـ received_buffer.

  12. Scatterالبعثرة مثال : يقوم البرنامج التالي بتعريف وتهيئة مصفوفة من الأعداد الصحيحة، ومن ثم توزيعها بالتساوي بين كافة العمليات في مجال الاتصال:

  13. #include<iostream> #include<mpi.h> using namespace std; void main(intargc, char** argv) { intsendArray[12]; intreceiveArray[12]; intprocessesNumber; intcurrentProcess; MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD,&processesNumber); MPI_Comm_rank(MPI_COMM_WORLD,&currentProcess); if((12%processesNumber)!=0) { MPI_Finalize(); return; } if(currentProcess==0){ for(inti=0;i<12;i++){ sendArray[i]=i+1; } } MPI_Scatter(sendArray,12/processesNumber,MPI_INT,receiveArray,12/processesNumber,MPI_INT,0,MPI_COMM_WORLD); cout<<"Process "<<currentProcess<<" has"<<endl; for(inti=0;i<12/processesNumber;i++) cout<<receiveArray[i]<<" "; cout<<endl; system("pause"); MPI_Finalize(); }

  14. Gattherالتجميع مثال : هنا يتم تجميع بيانات مختلفة من process مختلفة وتجمعيها في ال proess الجذر كما في الصورة التالية والتابع الذي يقوم بهذا الشئ في ال MPI هو : MPI_Gather( )

  15. Gattherالتجميع • الإجراء MPI_Gather له الصيغة التالية: intMPI_Gather ( void* send_buffer, intsend_count, MPI_Datatypesend_type, void* received_buffer, intreceive_count, MPI_Datatypereceive_type, int root, MPI_Commcomm) عند تنفيذ هذا التابع ، ستقوم كل process بإرسال محتويات الـsend_bufferفي مجال الاتصال comm إلى الـ process ذات الـ rank المساوي لـroot . وعندها تقوم الـ processذات الترتيب root بعملية وصل Concating للبيانات المستقبَلة بترتيب تصاعدي. ويمكن اعتبار الإجراء MPI_Gather الإجراء العكس للإجراء MPI_Scatter

  16. Gattherالتجميع • مثال : يقوم البرنامج التالي بتجميع عدة مصفوفات في مصفوفة واحدة:

  17. #include<iostream> #include<mpi.h> using namespace std; void main(intargc, char** argv) { intsendArray[12]; intreceiveArray[12]; intprocessesNumber; intcurrentProcess; MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD,&processesNumber); MPI_Comm_rank(MPI_COMM_WORLD,&currentProcess); if((12%processesNumber)!=0) { MPI_Finalize(); return; } for(inti=0;i<12/processesNumber;i++) sendArray[i]=(12/processesNumber)*currentProcess+i; MPI_Gather(sendArray,12/processesNumber,MPI_INT,receiveArray,12/processesNumber,MPI_INT,0,MPI_COMM_WORLD); if(currentProcess==0) { for(inti=0;i<12;i++) cout<<receiveArray[i]<<" "; cout<<endl; } MPI_Finalize(); }

  18. Gattherالتجميع مثال: في مثال برنامج حساب الأعداد الأولية الذي أخذ مسبقا بدلا من طباعة الأعداد الأولية في كل إجرائية قم بإرسال الأعداد الأولية الخمسة ألأولى المحسوبة في كل إجرائية إلى إجرائية واحدة وطباعتهم في تلك الإجرائية وفي حال كان العدد المحسوب أقل من 5تملىئ الرسالة المرسلة ب -1 حتى تصبح حجم الرسالة المرسلة 5والمجال هنا هو 5000 و 6000 .

  19. #include<iostream> #include<mpi.h> using namespace std; void main(intargc, char** argv){ intmynode, totalnodes; int x=5000; int y=6000; intprimeA[1000]; intprimteN[5]; intcountP=0; intstartval,endval; MPI_Status status; MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD, &totalnodes); // get totalnodes MPI_Comm_rank(MPI_COMM_WORLD, &mynode); // get mynode intlin=y-x; startval = (lin*(mynode))/totalnodes+x; endval =(lin*(mynode+1))/totalnodes+x; for(inti=startval;i<=endval;i++){ bool t=true; for(int m=2;m<i;m++){ if(i%m==0){ t=false; break; } } if(countP==5) break; if(t){ primteN[countP]=i; countP++; } }

  20. if(countP<5){ for(int j=countP;j<5;j++) primteN[j]=-1; } cout<<"the 5 prime in process "<<mynode<<" is:"<<endl; for(inti=0;i<5;i++) cout<<primteN[i]<<" "; cout<<endl; MPI_Gather(primteN,5,MPI_INT,primeA,5,MPI_INT,0,MPI_COMM_WORLD); if(mynode==0){ cout<<endl<<"Recevie array is "<<endl; for(int u=0;u<totalnodes*5;u++){ cout<<primeA[u]<<" "; }} system("pause"); MPI_Finalize(); }

  21. Gather-to-all : MPI_Allgather هذا التابع يقوم أولا بتجميع البيانات في جميع الإجرائيات بدلا من تجـمعيها في الـ process الجذر أي فعليا هو يعادل استدعاء MPI_gather ثم MPI_bcast أو ( استدعاء MPI_gather بعدد مرات ال processes ويكون مجال root process من 0 – n-1 حيث n عدد ال processes)

  22. Gather-to-all : MPI_Allgather الصيغة العامة للتابع int MPI_Allgather(void *sendbuf , int sendcount , MPI_Datatype sendtype , void *recvbuf, int recvcount , MPI_Datatype recvtype, MPI_Comm comm( عند تنفيذ هذا التابع ، ستقوم كل process بإرسال محتويات الـsend_bufferفي مجال الاتصال comm إلى كل الـprocesse. وعندها تقوم كل process بعملية وصل Concating للبيانات المستقبَلة بترتيب تصاعدي.

  23. Gather-to-all : MPI_Allgather مثال : البرنامج التالي يقوم بتوزيع قيم عشوائية بعدد الإجرائيات على جميع الإجرائيات حيث كل إجرائية تولد رقم عشوائي ويتم إرسال إلى جميع الإجرائيات

  24. #include<iostream> #include<mpi.h> using namespace std; void main(intargc, char** argv){ intmynode, totalnodes; intmyrand; int a[100]; MPI_Status status; MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD, &totalnodes); // get totalnodes MPI_Comm_rank(MPI_COMM_WORLD, &mynode); // get mynode myrand=rand()%100*(mynode+1); MPI_Allgather(&myrand,1,MPI_INT,a,1,MPI_INT,MPI_COMM_WORLD); cout<<"Processor "<<mynode<<" rand is "<<myrand<<endl; for(inti=0;i<totalnodes;i++) cout<<a[i]<<" "; cout<<endl; system("pause"); MPI_Finalize(); }

  25. MPI_Alltoall • هذا التابع يقوم بنقل البيانات من كل ال process إلى كل ال process كما في المخطط التاليأي فعليا يمكن القول أنه عبارة مجموعة توابع MPI_Scatter بحيث يكون قيم root من 0 إلى n-1 حيث n هو عدد الإجرائيات

  26. MPI_Alltoall int MPI_Alltoall(void *sendbuf , int sendcount, MPI_Datatype sendtype , void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm ( • يتم هنا توزيع sendcount من كلsendbuf الموجود في كل ( process ) إلى كل ال process حيث كل process تأخذ recvcount من كل porocess وفي حال كان عدد ال process أكبر من حجم المصفوفة الموزعة تحدث مشكلة حيث يؤدي ذلك إلى عدم حصول process على حصتها من الرسالة المرسلة

  27. MPI_Alltoall int MPI_Alltoall(void *sendbuf , int sendcount, MPI_Datatype sendtype , void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm ( • sendcount : هو عدد العناصر التي ترسل لكل process وليس عدد العناصر الموجودة في ال sendbuf . • recvcount: عدد العناصر المستقبلة من قبل كل process وليس العدد الكلي للعناصر السمتقبلة . • في جميع أمثلتنا • sendcount=recvcount, sendtype=recvtype

  28. MPI_Alltoall مثال : البرنامج التالي يقوم بتوزيع محتويات مصفوفة اسمها a موجودة في كل process على جميع ال processes الأخرى بحيث تحوي المصفوفة خمسة عناصر تمثل مضاعفات رتبة ( rank ) ال process وعدد الإجرائيات هنا هو 5

  29. #include<iostream> #include<mpi.h> using namespace std; void main(intargc, char** argv){ intmynode, totalnodes; int a[5]; int b[5000]; MPI_Status status; MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD, &totalnodes); // get totalnodes MPI_Comm_rank(MPI_COMM_WORLD, &mynode); // get mynode for(inti=0;i<5;i++) a[i]=mynode*(i+1); MPI_Alltoall(a,1,MPI_INT,b,1,MPI_INT,MPI_COMM_WORLD); cout<<"Processor "<<mynode<<" array is "<<endl; for(inti=0;i<5;i++) cout<<a[i]<<" "; cout<<endl; cout<<"Processor "<<mynode<<" Receve array is "<<endl; for(inti=0;i<5;i++) cout<<b[i]<<" "; cout<<endl; system("pause"); MPI_Finalize(); }

  30. وظيفة • اكتب برنامج تفرعي لإنجاز عملية البحث عن عدد داخل مصفوفة من الأعداد الصحيحة.

More Related