نموذج الحوسبة المتوازية

1 المقدمة. Corutinism التنافسية


كانت المقالات السابقة حول موضوع البرمجة التلقائية مجرد "زهور". "بيري" البرمجة التلقائية ، أي لما تحتاجه للقيام بذلك ، هو نموذج للحوسبة المتوازية على أساس نموذج آلة الدولة. لذا ، دعنا نذهب ...

يتضمن معيار C ++ الدعم الذي طال انتظاره لتعدد مؤشرات الترابط [1]. لكننا لن نعجب بها ولن ننتقد هذه الحقيقة ، لأن إن العمل مع الخيوط يثقله الكثير من الشروط ، والمحاذير ، والميزات التي بدون أمثلة حقيقية تكشف عن مشاكل تعدد المواضيع ، لن تكون مناقشة البرمجة متعددة الخيوط متسرعة فحسب ، بل تكون متحيزة إلى حد ما. لذلك ، في ما يلي بشكل رئيسي ليس عن التدفقات ، ولكن عن الأتمتة ، مع الأخذ في الاعتبار ، بالطبع ، أولها.

لغة C ++ بعيدة عن الأولى ، تستكملها بنيات موازية. في الستينيات من القرن الماضي ، اقترح N. Wirth امتدادًا موازيًا للغة ALGOL [2]. ومع ذلك ، فإن السنوات الستين المقبلة لم توضح ما يجب اعتباره خوارزمية موازية وما يجب أن يكون نموذج الحوسبة المتوازية. على ما يبدو ، يرتبط هذا الامتداد المتأخر للغة C ++ أيضًا بهذا.

كل من التركيبات القديمة للغة ALGOL ، ونظائرها الأكثر حداثة في لغة C ++ ، هي مجرد طرق موازية هيكلية لا تقدم نموذجًا خوارزميًا موازًا. لتبرير هذا ، يمكن القول أن المحاولات التي جرت على مدار الماضي لإنشاء مثل هذا النموذج الرسمي للحسابات قد باءت بالفشل. يكفي أن نقول أن نفس شبكات بيتري لم تبرر الآمال الكبيرة المعلقة عليها.

ونتيجة لذلك ، يبدو أن "دوامة" التوازي قد عادت إلى مصدرها ، بعد أن خضعت فقط "لتطور المصطلحات". أصبحت coroutines التافهة السابقة "coroutines" المتقدمة فجأة (ورقة تتبع من coroutine الإنجليزية) ، والارتباك مع مفاهيم التوازي والمتزامن في قسم اللغة الإنجليزية من البرمجة المتوازية يؤدي في بعض الأحيان إلى أشياء متناقضة. على سبيل المثال ، يختلف الإصدار الأول من الكتاب [1] عن الإصدار الثاني عن طريق استبدال المصطلحين "موازي" بمصطلح "تنافسي" و "متعدد مؤشرات الترابط" بمصطلح "مواز". لذا ، اكتشف ذلك في حالة "من هو".

2. نموذج آلي مواز للحسابات


ربما لن يجادل أحد في أن الخطوة النوعية التالية في تطوير البرمجة مرتبطة بالانتقال إلى نموذج الحوسبة المتوازي. ولكن ما إذا كان هذا سيحدث نتيجة للتطور التطوري للنموذج الحسابي الحالي أو ما إذا كان سيكون نموذجًا مختلفًا بشكل أساسي ، فإن القضية لا تزال قيد المناقشة. وإذا كان المنظرون لا يزالون يتجادلون ، فإن الجزء المتحمس عمليًا من المبرمجين يستخدم بالفعل أساليب هيكلية لموازاة البرامج.

يعتبر فصل الواجبات وزيادة الإنتاجية الأسباب الوحيدة لاستخدام التزامن. على الأقل لهم أو لمجموعاتهم تقليل أو محاولة الحد من كل الآخرين [1]. ولكن هناك سبب نادرًا ما يتم الحديث عنه ، ولكن بسببه من المفيد بشكل عام الانخراط في البرمجة المتوازية. في الواقع ، يمكن زيادة السرعة من خلال طرق الأجهزة البحتة ، ويرتبط الفصل بين المهام بالتوازي بنفس طريقة العمل اليومي لموظفي البنك مع قائمة بواجباتهم الرسمية. والخوارزميات المتوازية فقط هي استراتيجية تتيح لنا هزيمة تعقيد المهام وزيادة موثوقية البرامج. وكل هذا يتعارض مع الرأي السائد بشأن البرمجة متعددة الخيوط ، والتي تحول أي برنامج مواز إلى منتج برمجي معقد وغير موثوق به.

نظام مواز ، يتألف من العديد من المكونات والأشياء والعوامل المتفاعلة والمتفاعلة بشكل نشط ، ينفذ خوارزمية يتم تحديدها بطرق عديدة ليس من خلال خوارزميات المكونات الفردية (على الرغم من أنها بالطبع) ، ولكن من خلال عدد المكونات والعدد و نوع من الروابط بينهما. للتحكم في هذا التعقيد وفهم خوارزمية تشغيل النظام المتوازي ، لا تحتاج إلى نموذج حوسبة متوازي فحسب ، بل نموذج يحتوي ، من بين أمور أخرى ، وقبل كل شيء ، على نظرية مقابلة.

الفرضية القائلة بأن "البرنامج الموازي غالبا ما يكون أكثر صعوبة في الفهم ... وبالتالي ، فإن عدد الأخطاء في تزايد" ، بعبارة ملطفة ، قابلة للنقاش. نعم ، قد يكون من الصعب جدًا فهم خوارزمية البرنامج الموازي ، ولكن إذا كانت هناك نظرية ، فيمكن "حسابها" رسميًا باستخدام خوارزميات المكون. ومن وجهة نظر تصميم وتنفيذ وصيانة الخوارزميات المكونة أبسط بكثير من خوارزمية النظام ككل. عند تصميم مكونات أبسط ، من الواضح أننا سنرتكب أخطاء أقل من تصميم نظام في قطعة واحدة. علاوة على ذلك ، يمكن أن تكون المكونات المصححة جزءًا من أنظمة أخرى ، مما يقلل من التعقيد ، ويزيد من الموثوقية ويقلل من تكاليف التصميم.

3. التزامن التسلسلي


وصفت المقالة [3] التوازي لنموذج منفصل لآلة الحالة المحدودة. تحدد قنواته على مستوى تنفيذ التحولات التنفيذ الموازي للوظائف / الأساليب المرتبطة به - المسندات والإجراءات. في الوقت نفسه ، لا توجد قيود على التوازي المسند. عند العمل ، لا يتعارضون مع بعضهم البعض ، لأن لا تؤثر على محتويات الذاكرة. يمكن أن يكون للإجراءات ، التي تعمل بالتوازي ، بيانات إدخال ومخرجات مشتركة ، وكذلك تغييرها بشكل مستقل عن بعضها البعض. وكل هذا يمكن أن يكون مصدر عدم اليقين في قيمة بيانات الإخراج.

يوفر التشغيل الصحيح للإجراءات في الحالات الموضحة أعلاه ذاكرة ظل. من خلال تخزين قيم جديدة فيه ، يمكن للمرء استخدام نفس البيانات حتى في إجراء واحد ، كإدخال وإخراج. مثال على ذلك هو نموذج مولد النبض المستطيل ، الموصوف على أنه y =! Y ، حيث y هو خرج المولد. يظهر رمز C ++ الخاص به في بيئة VKPa في القائمة 1 ، وتظهر نتائج البرنامج في الشكل. 1.

قائمة 1. مولد نبض مستطيل
#include "lfsaappl.h"

class FSWGenerator :
    public LFsaAppl
{
public:
    LFsaAppl* Create(CVarFSA *pCVF) { Q_UNUSED(pCVF)return new FSWGenerator(pTAppCore, nameFsa, pCVarFsaLibrary); }
    bool FCreationOfLinksForVariables();
    FSWGenerator(TAppCore *pInfo, string strNam, CVarFsaLibrary *pCVFL);
    virtual ~FSWGenerator(void) {};
    CVar *pVarY;				//  
protected:
    void y1();
};

#include "stdafx.h"
#include "FSWGenerator.h"
// state machine transition table
static LArc TBL_SWGenerator[] = {
    LArc("s1",		"s1","--",	"y1"),			//
    LArc()
};

FSWGenerator::FSWGenerator(TAppCore *pInfo, string strNam, CVarFsaLibrary *pCVFL):
    LFsaAppl(TBL_SWGenerator, strNam, nullptr, pCVFL)
{
    pTAppCore = pInfo;
}
// creating local variables and initialization of pointers
bool FSWGenerator::FCreationOfLinksForVariables() {
// creating local variables
    pVarY = CreateLocVar("y", CLocVar::vtBool, " ");
    return true;
}
// setting output signals
void FSWGenerator::y1() {
    pVarY->SetDataSrc(nullptr, !bool(pVarY->GetDataSrc()));
}


صورة
تين. 1. محاكاة تشغيل مولد النبض المستطيل في VKPA

في هذه الحالة ، يكون للجهاز حالة واحدة مع انتقال غير مشروط (انتقال مع شرطة في مكان حالة الإدخال) في شكل حلقة مميزة بالإجراء y1 ، والتي تنفذ انعكاس متغير الإخراج ، والذي يشكل نبضة مستطيلة في الديناميكيات. في إطار نموذج الأوتوماتون ، يمكن التحكم في تردد إشارة النبض عن طريق تحديد قيمة اللباقة للوقت المنفصل لمساحة الأوتوماتون التي يتم تحميل الأوتوماتي فيها.

1. , . . . .


إن القدرة على التحكم في الوقت المنفصل للآلة الآلية ووجود العديد من المساحات الآلية ليست هي الخصائص الوحيدة ، ولكنها مهمة ومميزة لبيئة VKPa. باستخدامها ، يمكنك تحسين أداء البرنامج الموازي. على سبيل المثال ، يجب وضع الأجهزة التي تطبق تصور البيانات ومربعات حوار المستخدم في مساحات الأوتومات البطيئة ، ويجب توزيع عمليات التطبيق بين مساحات الأوتوماتيكية وفقًا للأولويات والسرعة المطلوبة ، إلخ. إلخ

في إطار نموذج آلي ، ترتبط قيمة خرج المولد بسهولة بالحالة الحالية للنموذج. يظهر رمز نموذج المولد ، الذي يحتوي بالفعل على حالتين ، كل منهما يعكس حالة إخراج المولد ، في القائمة 2.

قائمة 2. مولد موجة مربعة على الدول
#include "lfsaappl.h"

extern LArc TBL_SWGenState[];
class FSWGenState :
    public LFsaAppl
{
public:
    FSWGenState(TAppCore *pInfo, string strNam, CVarFsaLibrary *pCVFL):
    LFsaAppl(TBL_SWGenState, strNam, nullptr, pCVFL) {};
};

#include "stdafx.h"
#include "FSWGenState.h"
// state machine transition table
LArc TBL_SWGenState[] = {
    LArc("s0",		"s1","--",	"--"),			//
    LArc("s1",		"s0","--",	"--"),			//
    LArc()
};


في النموذج الجديد ، تحل الحالات محل متغير الإخراج ، وهذا ، كما يتبين ، يبسط بشكل كبير نموذج المولد. ونتيجة لذلك ، حصلنا على آلة "عارية" ، ممثلة فقط بجدول تحويل. لمراقبة حالتها الحالية "s1" في VKPa ، تم إنشاء متغير من نوع fsa (الحالة) بالاسم SWGenState. (S1) من أجل آلية تسمى SWGenState. يأخذ قيمة حقيقية في الحالة s1 ، وخطأ عندما يكون الجهاز في حالة مختلفة. علاوة على ذلك ، يتم استخدام هذا المتغير بالفعل عن طريق عرض بيانات بيئة VKPA (انظر اتجاه الإشارة في الشكل 2).

صورة
تين. 2. نمذجة مولد الدولة

4. نموذج التحكم الحوسبة المتوازية


علاوة على ذلك ، من خلال الانتقال إلى إنشاء نموذج للعمليات المتوازية ، من المنطقي استخدام العديد من آلات الحالة المحدودة التي تعمل وتتفاعل في وقت واحد ، أي شبكة الآلي. في هذه الحالة ، تظهر مشكلة اختيار نموذج وقت الشبكة ، والتي يمكن أن تكون هي نفسها لجميع الأجهزة أو ، في الحد الأقصى ، لكل منها. في VKPa ، تم الاختيار لصالح مرة واحدة (لمزيد من التفاصيل حول الشبكات المتزامنة للأتمتة ، انظر [5]).

يتيح لك الاختيار لمرة واحدة إنشاء جبر للأتمتة ذات عمليات تكوين وتفكك للأتمتة. باستخدام الأول ، يمكنك العثور على الأوتون الناتج ، الذي يعطي فكرة دقيقة عن تشغيل نظام مواز. وهنا تجدر الإشارة إلى الأطروحة أعلاه حول "تعقيد فهم" البرامج الموازية. يسمح لنا وجود عملية التكوين بحل "مشكلة الفهم" للبرنامج الموازي.

بالطبع ، يمكن أن يكون المحرك الناتج لشبكة من عدد كبير من المكونات ضخمًا جدًا. ولكن ، لحسن الحظ ، هناك حاجة في كثير من الأحيان إلى فهم تشغيل الأنظمة الفرعية أو الشبكات لعدد صغير من المكونات ، والتي لا يؤدي العثور على المحرك الآلي إلى حدوث مشاكل كبيرة. يوضح المثال التالي نموذج RS-flip-flop هذا.

نموذج الزناد RS هو مثال على نظام مواز بسيط. من المثير للاهتمام بشكل خاص في وجود ردود فعل متقاطعة. التغذية المرتدة ، أو ، بطريقة أخرى ، السلاسل الدورية ، الحلقات ، الحلقات الجبرية ، إلخ. تمثل حاليًا مشكلة خطيرة للنماذج الهيكلية للأنظمة المتوازية. في الحالة العامة ، يُسمح بذلك من خلال إدخال حلقات فجوة لعناصر الذاكرة. هذا هو الحل المعياري الذي تقترحه نظرية الأتمتة [4]. يوصى بنفس الناتج في شخص MATLAB. تختلف بيئة VKPa من حيث أنها لا تتطلب إدخال مثل هذه العناصر الإضافية لتنفيذ الحلقات. لاحظ أن هذا مهم جدًا ، فالدوائر الحقيقية أيضًا لا تحتاجها (انظر دائرة RS-flip-flop).

في التين. يعرض الشكل 3 أبسط نموذج للعنصر AND-NOT ، والذي تتكون منه دائرة الزناد RS. لا يأخذ في الاعتبار تأخيرات العناصر ، وكذلك نوعها (تأخيرات النقل أو القصور الذاتي). ومع ذلك ، فإنه لا يزال يحتوي على إيقاع تأخير واحد على الأقل. هذا هو وقت الانتقال من دولة إلى أخرى. تظهر القائمة 3 رمز النموذج

صورة
. 3. نموذج العنصر وليس

قائمة 3. نموذج العنصر وليس
#include "lfsaappl.h"

class FIne :
    public LFsaAppl
{
public:
    LFsaAppl* Create(CVarFSA *pCVF) { Q_UNUSED(pCVF)return new FIne(pTAppCore, nameFsa, pCVarFsaLibrary); }
    bool FCreationOfLinksForVariables();
    FIne(TAppCore *pInfo, string strNam, CVarFsaLibrary *pCVFL);
    virtual ~FIne(void) {};
    CVar *pVarX1;				//  
    CVar *pVarX2;				//  
    CVar *pVarY;				//  
    CVar *pVarStrNameX1;		//    
    CVar *pVarStrNameX2;		//    
    CVar *pVarStrNameY;         //   
protected:
    int x1(); int x2(); int x12();
    void y1(); void y2(); void y12();
    bool bX1, bX2, bY;
};


#include "stdafx.h"
#include "FIne.h"
// state machine transition table
static LArc TBL_Ine[] = {
    LArc("st",		"st","^x12","y12"), 		//
    LArc("st",		"s1","x12^x1",	"y1"),		//
    LArc("st",		"s1","x12^x2",	"y1"),		//
    LArc("st",		"s0","x12x1x2",	"y2"),		//
    LArc("s1",		"s0","x1x2",   "y2"),		//
    LArc("s0",		"s1","^x1",    "y1"),		//
    LArc("s0",		"s1","^x2",    "y1"),		//
    LArc()
};

FIne::FIne(TAppCore *pInfo, string strNam, CVarFsaLibrary *pCVFL):
    LFsaAppl(TBL_Ine, strNam, nullptr, pCVFL)
{ }

// creating local variables and initialization of pointers
bool FIne::FCreationOfLinksForVariables() {
// creating local variables
    pVarX1 = CreateLocVar("x1", CLocVar::vtBool, " 1- ");
    pVarX2 = CreateLocVar("x2", CLocVar::vtBool, " 2- ");
    pVarY = CreateLocVar("y", CLocVar::vtBool, " ");
    pVarStrNameX1 = CreateLocVar("strNameX1", CLocVar::vtString, "name of external input variable(x1)");			//   
    pVarStrNameX2 = CreateLocVar("strNameX2", CLocVar::vtString, "name of external input variable(x2)");			//   
    pVarStrNameY = CreateLocVar("strNameY", CLocVar::vtString, "name of external output variable(y)");		//   
// initialization of pointers
    string str;
    if (pVarStrNameX1) {
        str = pVarStrNameX1->strGetDataSrc();
        if (str != "") { pVarX1 = pTAppCore->GetAddressVar(str.c_str(), this);	}
    }
    if (pVarStrNameX2) {
        str = pVarStrNameX2->strGetDataSrc();
        if (str != "") { pVarX2 = pTAppCore->GetAddressVar(str.c_str(), this); }
    }
    if (pVarStrNameY) {
        str = pVarStrNameY->strGetDataSrc();
        if (str != ""){pVarY = pTAppCore->GetAddressVar(str.c_str(), this);}
    }
    return true;
}

int FIne::x1() { return bool(pVarX1->GetDataSrc()); }
int FIne::x2() { return bool(pVarX2->GetDataSrc()); }
int FIne::x12() { return pVarX1 != nullptr && pVarX2 && pVarY; }

void FIne::y1() { pVarY->SetDataSrc(nullptr, 1); }
void FIne::y2() { pVarY->SetDataSrc(nullptr, 0.0); }
void FIne::y12() { FInit(); }


في التين. يوضح الشكل 4 رسمًا تخطيطيًا لـ RS flip-flop ونموذجه في شكل آلة حالة محدودة. تشير الأسهم الموجودة في النموذج إلى الروابط بين البيانات التلقائية للشبكة. هنا ، من جهة ، تعكس حالات النماذج حالات مخرجات العنصر ، ومن ناحية أخرى ، يتم استخدامها أيضًا كإشارات لتنظيم روابط المعلومات بين العمليات المتوازية. هذا الشكل من النموذج (مع التزامن من خلال الحالات) هو الذي يجعل من السهل العثور على المحرك الآلي للشبكة. موضح في الشكل. 5 (للاطلاع على إجراء العثور على الأوتوماتيكية الناتجة ، انظر [6] لمزيد من التفاصيل).

قارن الخوارزمية [الناتجة] لبرنامج RS-flip-flop الموازي وخوارزمية التشغيل لعنصر AND-NOT منفصل. الفرق مذهل. في هذه الحالة ، يتم إنشاء خوارزميات المكون بواسطة "مقابض" ، ويتم إنشاء خوارزمية النظام الموازي ضمنيًا - بواسطة "الذكاء الاصطناعي" للشبكة. هذا هو الفرق النوعي بين البرامج المتوازية والبرامج المتسلسلة: تغيير الاتصالات فقط (واحد على الأقل) ، سنحصل على خوارزمية عمل مختلفة تمامًا. وبالتأكيد لن يكون مشغل RS بعد الآن. وبالمناسبة ، إنسان آخر ينتج.

صورة
تين. 4. مخطط RS-FF ونموذج الشبكة

صورة
الشكل. 5. نموذج شبكة آلة الناتج RS- الزناد

تحليل الآلي الناتج في الشكل. 5 يعطي "الفهم" التالي للبرنامج الموازي (والزناد الحقيقي بالطبع). أولاً ، عند التحول من دولة إلى أخرى ، فإن الزناد سوف يمر بالضرورة بالحالة "المحظورة" للمخرجات (وماذا تقول الكتب عن هذا؟). ثانيًا ، إذا كان الزناد مدفوعًا إلى حالة واحدة من المخرجات (في الحالة "s1w1") ، ثم يتم إدخال وحدتين إلى المدخلات ، فسوف يدخل إلى وضع الإنشاء ، أي التبديل الدوري بين الدول "s1w1" و "s0w0" و (وهل سمعت عن توليد الزناد؟).

يحدث الانتقال من خلال حالة ممنوعة أيضًا في محفز حقيقي ، ولكن وضع التوليد مستحيل بسبب الاختلاف في تأخيرات العناصر الحقيقية. تين. يوضح الشكل 6 طريقة توليد نموذج الزناد ، والذي يوجد طالما يتم تخزين الوحدات عند المدخلات.

ملاحظة 2. يتم إعطاء وصف نموذجي لتشغيل الزناد RS في الغالبية العظمى من الحالات في شكل جدول الحقيقة. ولكن للقيام بذلك ، مع إدراك أن الزناد هو مخطط متسلسل ، فهو في الواقع يضلل عمداً أولئك الذين يدرسون هذا الموضوع. حسنًا ، لا يمكن لأي زناد أن يكون لديه "حالات ممنوعة"! ولكن لسبب ما ، قرر عدد قليل فقط اكتشاف هذه الحقيقة ، ولا سيما مناقشة مشكلة جيلها (انظر ، على سبيل المثال ، [7]).


تين. يوضح الشكل 7 تبديل نموذج الزناد بين حالاته المستقرة. هنا ، تحتفظ حالة واحدة من إدخالات الزناد بالحالة الحالية لمخرجات الزناد ، وعندما يتم تعيين هذا الإدخال أو ذلك الإدخال على صفر ، فإنه يتحول إلى الحالة المعاكسة. في الوقت نفسه ، عندما يتم تبديل الزناد ، فإن مخرجاته في الوقت الحالي تساوي تدبيرًا منفصلاً واحدًا تأخذ في نفس الوقت دولة واحدة (ممنوعة من قبل؟).

صورة
تين. 6. وضع توليد RS- الزناد

صورة
الشكل. 7. تبديل RS الزناد بين الدول

ضع في اعتبارك نموذجًا آخر لتشغيل RS ، يتكون من حالة واحدة وعمل واحد ، أي مشابه للنموذج الموجود في القائمة 1. يظهر رمزه في القائمة 4. هذا النموذج ، مثل نموذج المولد ، ليس له أي تقديرات ويتم إدخال قيم الإشارة دون أي تحويلات وسيطة إلى الإجراء y1. هل هذا جيد أم سيء؟ من ناحية ، يبدو أنه جيد ، لأنه أصبح الرمز أكثر بساطة ، ولكن من ناحية أخرى ... ليس حقًا. وسوف نفهم أسباب ذلك الآن.

الإدراج 4. نموذج عنصر NAND من إجراء واحد
#include "lfsaappl.h"

class FTwoOperators :
    public LFsaAppl
{
public:
    LFsaAppl* Create(CVarFSA *pCVF) { Q_UNUSED(pCVF)return new FTwoOperators(pTAppCore, nameFsa, pCVarFsaLibrary); }
    bool FCreationOfLinksForVariables();
    FTwoOperators(TAppCore *pInfo, string strNam, CVarFsaLibrary *pCVFL);
    virtual ~FTwoOperators(void) {};
    CVar *pVarX1;				//  
    CVar *pVarX2;				//  
    CVar *pVarY;				//  
    CVar *pVarStrNameX1;		//    
    CVar *pVarStrNameX2;		//    
    CVar *pVarStrNameY;         //   
protected:
    int x12();
    void y1(); void y12();
    bool bX1, bX2, bY;
};

#include "stdafx.h"
#include "FTwoOperators.h"
// state machine transition table
static LArc TBL_TwoOperators[] = {
    LArc("st",		"st","^x12","y12"), 		//
    LArc("st",		"s1","x12", "--"),		//
    LArc("s1",		"s1","--",  "y1"),		//
    LArc()
};

FTwoOperators::FTwoOperators(TAppCore *pInfo, string strNam, CVarFsaLibrary *pCVFL):
    LFsaAppl(TBL_TwoOperators, strNam, nullptr, pCVFL)
{ }
// creating local variables and initialization of pointers
bool FTwoOperators::FCreationOfLinksForVariables() {
// creating local variables
    pVarX1 = CreateLocVar("x1", CLocVar::vtBool, " 1- ");
    pVarX2 = CreateLocVar("x2", CLocVar::vtBool, " 2- ");
    pVarY = CreateLocVar("y", CLocVar::vtBool, " ");
    pVarStrNameX1 = CreateLocVar("strNameX1", CLocVar::vtString, "name of external input variable(x1)");			//   
    pVarStrNameX2 = CreateLocVar("strNameX2", CLocVar::vtString, "name of external input variable(x2)");			//   
    pVarStrNameY = CreateLocVar("strNameY", CLocVar::vtString, "name of external output variable(y)");		//   
// initialization of pointers
    string str;
    if (pVarStrNameX1) {
        str = pVarStrNameX1->strGetDataSrc();
        if (str != "") { pVarX1 = pTAppCore->GetAddressVar(str.c_str(), this);	}
    }
    if (pVarStrNameX2) {
        str = pVarStrNameX2->strGetDataSrc();
        if (str != "") { pVarX2 = pTAppCore->GetAddressVar(str.c_str(), this); }
    }
    if (pVarStrNameY) {
        str = pVarStrNameY->strGetDataSrc();
        if (str != "") { pVarY = pTAppCore->GetAddressVar(str.c_str(), this);	}
    }
    return true;
}

int FTwoOperators::x12() { return pVarX1 != nullptr && pVarX2 && pVarY; }

void FTwoOperators::y1() {
// reading input signals
    bX1 = bool(pVarX1->GetDataSrc());
    bX2 = bool(pVarX2->GetDataSrc());
// setting output signals
    bY = !(bX1&&bX2);
    pVarY->SetDataSrc(nullptr, bY);
}
// initialization of pointers
void FTwoOperators::y12() { FInit(); }


إذا اختبرنا النموذج الجديد في وضع "ذاكرة الظل" ، فلن نرى أي اختلافات في تشغيله عن النموذج السابق ، أي والتبديل ، سوف يمر عبر الحالات المحظورة ويدخل بانتظام في وضع التوليد. إذا قمنا بإعداد العمل باستخدام البيانات في الوضع المعتاد ، فسوف نحصل على النتائج الموضحة في الشكل. 8 والتين. 9.

صورة
الشكل 8. فشل وضع توليد نموذج الزناد RS

صورة
. 9. تخطي الحالات الممنوعة بواسطة

نموذج RS- الزناد لماذا النموذج الأول ، بغض النظر عن طريقة العمل مع الذاكرة ، يظهر نتائج مستقرة ، والثاني - يغير السلوك؟ السبب هو المسندات. النموذج الثاني ليس له أي إسقاطات ، وهذا أمر بالغ الأهمية لسلوكه. ولكن كيف ولماذا يؤثر وجود / عدم وجود المسندات على خوارزمية تشغيل البرنامج الموازي؟

يحتوي نموذج البرنامج الخاص بعنصر AND-NOT ، مثل برنامج التشغيل الآلي ، على قناتي إدخال وقناة إخراج واحدة. يجب أن تتطابق مع اثنين من المسندات وعمل واحد. البرنامج الأول يتفق تماما مع هذا. نواة VKPa ، التي تفسر وصف الأوتوماتون ، تقوم أولاً بتنفيذ جميع المسندات ليس فقط آلة أوتوماتيكية معينة ، ولكن أيضًا مساحة الأوتوماتون بأكملها ، وعندها فقط تبدأ جميع الإجراءات. في هذه الحالة ، في أي تسلسل تم تنفيذ الإجراءات ، ومحاكاة التوازي ، وفي أي وضع عملت فيه مع الذاكرة ، لا تعتمد نتائج المسندات على دورة الساعة الحالية للآلة عليها (الإجراءات). لذلك ، ينتج البرنامج الأول نفس النتيجة.

البرنامج الثاني ، على الرغم من أنه يعمل مباشرة مع قنوات إدخال الجهاز ، يقرأ إشارات الإدخال كجزء من الإجراء. تعمل الإجراءات ، باستخدام بيانات الإدخال في وضع ذاكرة الظل ، على كتابة قيم جديدة إلى ذاكرة الظل وبالتالي العمل مع البيانات الصالحة في بداية دورة ساعة منفصلة. في الوضع المعتاد ، "يمسكون" بالقيم الآنية التي تم تحديدها وقت تغييرها ، وبالتالي تصبح الخوارزمية معتمدة على لحظات تغيير الذاكرة. ويظهر البرنامج الثاني اعتمادًا مشابهًا. وحتى إذا تم إدخال الطرق الأصلية في النموذج الثاني ، فلن يكون لذلك أي تأثير على نتائج عمله. ما يهم هنا ليس حقيقة وجود طرق أصلية ، ولكن ميزات عملها في إطار نموذج البرمجة الآلية.

5. الاستنتاجات


باستخدام برنامج الزناد RS الموازي كمثال ، قمنا بفحص بعض الخصائص الكامنة في أي برنامج مواز. سنواصل النظر في بعض الجوانب العامة لعمل البرامج المتوازية كمثال على الدوائر المنطقية (الرقمية). اختيار موضوع نمذجة الدوائر الرقمية هنا ليس صدفة. في الواقع ، في "شكل مصقول" يمثلون عمل عمليات موازية. هذا يجعل تحليل الفروق الدقيقة للتوافق والعرق والمزامنة والطرق المسدودة وما إلى ذلك. الخ شفافة وواضحة وبسيطة.

في نفس الوقت ، بغض النظر عن كيفية استدعاء البرمجة - "تنافسية" أو موازية ، سواء كنت تستخدم "coroutines" أو coroutines أو خيوط أو آلات للبرمجة ، يجب أن تكون نتيجة البرنامج [الموازي] هي نفسها في جميع عمليات التنفيذ. يسعى النموذج التلقائي للبرامج الموازية في إطار CPSU إلى تحقيق هذا الهدف فقط.
أيا كانت الافتراضات التي ستوضع فيما يتعلق بتنفيذ جوهر تفسير الآلي من بيئة VKPa ، كل هذه ستكون "المضاربات" ، لأنه لا ينبغي أن ترتبط نتيجة عمل البرامج التلقائية بتنفيذ نموذج حسابي. يمكن أن يكون برنامجًا (كما هو الآن) أو جهاز (كما آمل في المستقبل) ، يتم تنفيذه على قلب واحد أو على مجموعته ، في نسخة واحدة أو متعددة الخيوط ، إلخ. إلخ كل هذا لا ينبغي أن يؤثر بأي شكل من الأشكال على نتائج البرامج التلقائية المتوازية.

ويبدو أن الهدف قد تحقق. نموذج RS- الزناد ، باعتباره أحد اختبارات التوازي للأنظمة المحتملة [8] ، يقنع هذا ... كما أظهرت الحياة ، جميع البرامج المتوازية الأخرى ، بشرط أن تقوم البيئة بتشغيل اختبار الزناد RS بنجاح بالتوازي ، تعمل بشكل صحيح وموثوق ومستقر . بالمناسبة ، لم ينجح MATLAB "اختبار الزناد RS" ، وهذا يقول بالفعل الكثير ...

المؤلفات
1. . ++ . . . . .. – .: , 2012. – 672 .
2. . : . . – .: , 1981. – 360 .
3. . [ ], : habr.com/ru/post/484588 . . . ( 07.01.2020).
4. .. . .: , 1962.
5. .., - .. . – 2- ., . . – .: , 1988. – 480 .
6. .. . [ ], : cloud.mail.ru/public/HwsK/T95PMM8Ed . . . ( 01.02.2020).
7. . . 2- . – .: , 2004. – 432.
8. .. ? “ ”, №10/97, .116-119. [ ], : www.osp.ru/pcworld/1997/10/158015 . . . ( 01.02.2020).

Source: https://habr.com/ru/post/undefined/


All Articles