الجلسة الثانية - Eng . Rami Mahfoud
Download
Report
Transcript الجلسة الثانية - Eng . Rami Mahfoud
البرمجة التفرعية
الجلسة الثانية
Eng. rami mahfoud http://irami.im
•
•
العملية ( )processهي برنامج يقوم بانجاز مهمة ( ) taskعلى المعالج
كل معالج في نظام تبادل الرسائل يقوم بتشتغيل نسخة من البرنامج instance/copy of a program
بحيث :
–
–
–
•
•
•
•
تكون مكتوبة بواسطة لغة متسلسلسة .مثل c++
غاليا ما يكون برنامج وحيد يتم تطبيقه على مجموعات متعددة من البيانات
المتحوالت في كل برنامج فرعي تحوي :
نفس أسماء المتحوالت
لكن أماكن تواجدها مختلفة ( ذواكر موزعة ) وبيانات مختلفة
كل المتحوالت تكون محلية بالنسبلة للعملية .يتم التراسل بواسطة إجراءات ( ) routinesإرسال واستقبال تسمى تبادل الرسائل
data
program
communication network
MPI Course
2
توزيع العمل والبيانات
( معرفات للتواصل فيما بنيهاmpi-processes ( mpi • تحتاج عمليات ال
rank = identifying number
العمليةrank ) • كل عمليات التوزيع تعتمد على ) رتبة
myrank=0
myrank=1
myrank=2
myrank=
(size-1)
data
data
data
data
program
3
program
program
communication
network
MPI Course
program
SPMD
Single Program, Multiple Data •
Same (sub-)program runs on each processor •
MPI allows also MPMD, i.e., Multiple Program, ... •
MPMD can be emulated with SPMD –
4
Emulation of MPMD
• main(int argc, char **argv){
if (myrank < .... /* process should run the ocean model */){
ocean( /* arguments */ );
}else{
weather( /* arguments */ );
}
}
5
مبادئ ال MPI
• تتكون ال MPIمن 128تابع ولكن فعليا هناك 6توابع يمكن عن
طريقها حل معظم المسائل التفرعية وهي :
MPI_Init
MPI_Comm_size
MPI_Comm_rank
MPI_Send
MPI_Recv
MPI_Finalize
•
•
•
•
•
•
6
MPI مثال عن بنية البرنامج في بيئة
ورقمهاHello World برنامج تقوم فيه كل عملية بطباعة: لنأخذ أبسط مثال
#include<iostream>
#include<mpi.h>
using namespace std;
void main(int argc, char** argv)
{
int mynode,totalnodes;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&totalnodes);
MPI_Comm_rank(MPI_COMM_WORLD,&mynode);
cout<<"HELLO WORLD FROM PROCESS "<<mynode;
cout<<" of "<<totalnodes<<endl;
system("pause");
MPI_Finalize();
}
•
• التعليمة األولى تقوم بتضمين الملف الرأسي الخاص بالدخل
والخرجInput/Output Stream
• التعليمة الثانية تقوم بتضمين الملف الرأسي الحاوي على روتينات المعيار .MPI
• التعليمة الثالثة تقوم بتضمين فضاء األسماء stdضمن البرنامج ،وبذلك نختصر
في الكتابة فعوضا ً عن كتابة:
" Std::cout<<"someWordsنكتب هذه التعليمة ،عند استخدام فضاء األسماء
،stdبالشكل:
;"cout<<"someWords
• في السطر الرابع لدينا الـ ،mainوكما نعلم في C++الـ mainهو تابع
والـ argumentsداخل قوسيه هي المتحوالت الممررة له من برنامج آخر ،غالبا ً
يكون البرنامج اآلخر هو الـ ( system shellمثل cmdفي :)Windows
• :int argcاختصار لـ ،Argument Countوهو عدد األشياء الممررة إلى
البرنامج.
• ][ :char **argv or char *argvاختصار لـ ،Argument Vectorوهي
مصفوفة عناصرها من النوع مؤشر إلى محرف ،تُستخدم لتخزين األشياء التي
ستمرر إلى البرنامج.
•
اإلجراء : MPI_Initيجب استدعاءه قبل استدعاء أي إجراء آخر من مكتبة MPIألنه
المسؤول عن تهيئة بيئة MPIللعمل ،في نهاية تنفيذ هذا اإلجراء في الذاكرة سيتم نسخ قائمة
الوسطاء الممررة للبرنامج ،وهنا يجب مالحظة أن النسخ ليس ضروري تبعا ً للمعيار ،MPIلكنه
مجرد توسيع لتحقيق إمكانية توزيع المتحوالت الممررة للبرنامج إلى جميع العمليات التي تنفذ
ّ
على اآلالت المختلفة .لكننا ال نترك القوسين في اإلجراء السابق فارغين حيث سيسبب ذلك خطأ
ترجمة.
•
توضيح :يمكننا كتابة الكود التالي:
;char ** b
;int a
;)MPI_Init(&a,&b
• ومن الجدير بالذكر أن بيئة MPIال ترى من البرنامج إال ما هو محصور بين اإلجرائين:
) MPI_Init(&argc,&argvو )(.MPI_Finalize
• اإلجراء : MPI_Comm_Sizeيحدد عدد العمليات التي تنفذ في الـ
( communicatorالـ communicatorهونظام اتصال مثل الـ
،mail system, phone systemوكل رسالة تمر عبر مكالمة في
النظام لديها متحول من النوع ،communicatorوالـ
communicatorاالفتراضي هو الـ MPI_COMM_WORLD
الذي ينشأ بواسطة اإلجراء MPI_Initوهو يضم جميع العمليات،
سنوضح ذلك الحقا ً).
• اإلجراء MPI_Comm_sizeله الشكل التالي :
(MPI_Comm_size
MPI_Comm comm, /* in */
int *size
/*out*/
)
• حيث commهو غرض من MPI_Commالذي يمثل ال
communitcationالحالي و sizeهو مؤشر إلى قيمة صحيحة
تمثل عدد اإلجرائيات الكلي
• اإلجراء MPI_Comm_rankيحدد رقم العملية المستدعاة
حالياً ،وهو رقم نسبي للعملية بين مجموعة العمليات.
• وله الشكل التالي :
(MPI_Comm_rank
MPI_Comm comm, /* in */
int *rank
/*out */
)
• حيث commهو غرض من MPI_Commالذي يمثل ال
communitcationالحالي و rankهو مؤشر إلى قيمة
صحيحة تمثل رتبة ( ) rankاإلجرائية ( )process
• اإلجراء MPI_Finalizeيُستدعى عند انتهاء تنفيذ العمليات
كلها ،ويسبب انتهاء عمل بيئة ،MPIلكنه ال يسبب توقيف
العمليات التي ال تزال في التنفيذ ،وإنما ينتظر انتهاء تنفيذها (حيث
يوجد إجراء آخر يقوم بإحباط تنفيذ كل العمليات حتى التي ال تزال
في التنفيذ هو )MPI_Abort
• كل عملية من العمليات (المحدد عددها سابقا ً) تبدأ بالتنفيذ بشكل
مستقل عن األخريات بدءا ً من التعليمة MPI_Initوحتى
التعليمة .MPI_Finalize
• ;)" system("pauseهي تعليمية ال دخل لها بال mpiوتوضع
فقط للمحافظ على نوافذ التنفيذ حتى ال تختفي بمجرد انتهاء التنفيذ
يمكن االستعاضة عنها بوضع Break Pointمكانها
•
تنفيذ البرنامج بواسطة mpiexec
يتم تشغيل ال cmdوالذهاب لمجلد الملف التنفيذي للبرنامج
وكتابة التعليمة التالية
mpiexec –n ProcessNumber ProjectName
حيث
: ProcessNumberتمثل عدد المعالجات
: ProjectNameاسم المشروع ( اسم الملف التنفيذي )
تراسل المعطيات في MPI
• يعد إرسال واستقبال الرسائل تقنية االتصال األساسية في
،MPIعمليتي االتصال األساسيتين من النوع point-to-
pointهما sendو : receive
تراسل المعطيات في MPI
( MPI_Send
/*in*/
/*in*/
/*in*/
/*in*/
/*in*/
/*in*/
•
•
•
•
•
•
message
count
datatype
dest
tag
comm
* void
int
MPI_Datatype
int
int
MPI_Comm
)
:messageالمتحول الموجود في ذاكرة العملية المرسلة وهو فعليا موقع في الذاكرة يشير إلى موقع بداية
العناصر المرسلة
:countعدد عناصر الرسالة.
:datatypeأنواع المعطيات للعناصر المرسلة وهو من النمط MPI_Datatypeالذي سيتم شرحه
:destرتبة اإلجرائية المستقبلة.
:tagالحقة الرسالة ،يبين بعض المعلومات عنها.
:commيحدد مجال االتصال.
تراسل المعطيات في MPI
(MPI_Recv
/*out*/
/*in*/
/*in*/
/*in*/
/*in*/
/*in*/
/*out*/
message
count
datatype
source
tag
comm
status
* void
int
MPI_Datatype
int
int
MPI_Comm
* MPI_Status
)
• :messageالمتحول الموجود في ذاكرة العملية المستقبلة وهو فعليا موقع في الذاكرة يشير إلى موقع بداية العناصر المستقبلة
والموجودة في الذاكرة المؤقتة buffer
• :countعدد عناصر المستقبلة.
• :datatypeأنواع المعطيات للعناصر المستقبلة وهو من النمط MPI_Datatypeالذي سيتم شرحه
• :sourceرتبة اإلجرائية المرسلة.
• :tagالحقة الرسالة ،يبين بعض المعلومات عنها.
• :commيحدد مجال االتصال.
:statusيعطي حالة الرسالة المستقبلة وهو عبارة عن سجل يحوي الحقول التالية :
count
cancelled
MPI_SOURCE
MPI_TAG
MPI_ERROR
int
int
int
int
int
MPI أنواع البيانات القياسية في
C++ باإلضافة إلى أنواع جديدة غير موجودة في،MPI مقابل فيC++ لكل نوع من أنواع البيانات في
والسبب هو أنه قد نوزع البرنامج على معالجات يكون.)MPI_PACKED وMPI_BYTE (مثل
.MPI ومقابالتها فيC++ تمثيل األنماط فيه مختلف الجدول التالي يوضح أنواع البيانات في
MPI أنواع البيانات في
C++ أنواع البيانات في
MPI_CHAR
MPI_SHORT
MPI_INT
MPI_LONG
MPI_UNSIGNED_CHAR
MPI_UNSIGNED_SHORT
MPI_UNSIGNED
MPI_UNSIGNED_LONG
MPI_FLOAT
MPI_DOUBLE
MPI_LONG_DOUBLE
MPI_BYTE
MPI_PACKED
signed char
signed short int
signed int
signed long int
unsigned char
unsigned short int
unsigned int
unsigned long int
float
double
long double
•
---------
: قم بزيارة الرابط التاليvs 2010 ضمنc++ لمعرفة حجم األنماط في
•
http://msdn.microsoft.com/en-us/library/s3f49ktz(v=vs.100).aspx
•
إرسال رسالة بين عمليتين: مثال
#include<mpi.h>
#include<iostream>
using namespace std;
void main( int argc, char ** argv )
{
char message[20];
int myrank;
MPI_Status status;
MPI_Init( &argc, &argv );
MPI_Comm_rank( MPI_COMM_WORLD, &myrank );
if (myrank == 0) //code for process zero
{
strcpy(message,"Hello, there");
MPI_Send(message, strlen(message)+1, MPI_CHAR, 1, 99, MPI_COMM_WORLD);
}
else if (myrank == 1) //code for process one
{
MPI_Recv(message, 20, MPI_CHAR, 0, 99, MPI_COMM_WORLD, &status);
cout<<"recieved: "<<message<<" From Process:"<<status.MPI_SOURCE<<endl;
cout<<"data size:"<<status.count;
}
MPI_Finalize();
}
مثال – جمع األعداد
إلى1 • لنفرض أننا نريد كتابة برنامج يقوم بجمع األعداد من
البرنامج التسلسي يكون1000
#include<iostream>
using namespace std;
int main(int argc, char ** argv){
int sum;
sum = 0;
for(int i=1;i<=1000;i=i+1)
sum = sum + i;
cout<< "The sum from 1 to 1000 is: " << sum << endl;
}
: البرنامج التفرعي يكون
#include<iostream>
#include<mpi.h>
using namespace std;
int main(int argc, char** argv){
int mynode, totalnodes;
int sum,startval,endval,accum;
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
sum = 0; // zero sum for accumulation
startval = 1000*mynode/totalnodes+1;
endval =1000*(mynode+1)/totalnodes;
for(int i=startval;i<=endval;i++)
sum = sum + i;
if(mynode!=0)
MPI_Send(&sum,1,MPI_INT,0,1,MPI_COMM_WORLD);
else
for(int j=1;j<totalnodes;j++){
MPI_Recv(&accum,1,MPI_INT,j,1,MPI_COMM_WORLD, &status);
sum = sum + accum;
}
if(mynode == 0)
cout << "The sum from 1 to 1000 is: " << sum << endl;
system("pause");
MPI_Finalize();
}
تمرين
• اكتب برنامج تفرعي يقوم بحساب األعداد األولية بين
100000000و 400000000وكل عملية تقوم بطباعة
األرقام األولية التي تجدها .
حل التمرين
#include<iostream>
#include<mpi.h>
using namespace std;
int main(int argc, char** argv){
int mynode, totalnodes;
int x=100000000;
int y=400000000;
int startval,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
int lin=y-x;
حل التمرين
startval = (lin*(mynode))/totalnodes+x;
endval =(lin*(mynode+1))/totalnodes+x;
for(int i=startval;i<=endval;i++){
bool t=true;
for(int m=2;m<i;m++){
if(i%m==0){
t=false;
break;
}
}
if(t){
cout<<i<<"--";
}
}
system("pause");
MPI_Finalize();
}