تكتيكات لتحقيق أقصى سرعة لتنفيذ الشيفرة [مترجم]
#1
السلام عليكم ورحمة الله تعالى وبركاته
قرأت مقالة عن تكتيكات لتحقيق أقصى سرعة لتنفيذ البرنامج في موقع غربي (فرنسي)
و قلت لنفسي لما لا أشاركها مع إخواني في منتدى دلفي للعرب
لكن المشكلة هي أنه إخواني في المشرق - أغلبهم- لا يحسنون اللغة الفرنسية
لذلك روادتني الفكرة، لما لا أجرب وأترجمها لعلها البداية إلى زيادة كسب العلم من مصادر غير العربية و الاستفادة من خبراتهم.
و للعلم لم أنقلها إلا بعد موافقة صاحبها المؤلف (مرفوقة).
وأنوه أنني لست مترجما لذلك كل من رأى سوء ترجمة أو غموض أن يصححه بالتنويه او مراسلة المشرفين
ثم سنصدر نسخا منقحة بعد كل تصحيح (النسخة الحالية 0.1)
أنظر المشاركة اللاحقة
تحياتي Smile
الرد
#2
تكتيكات لتحقيق أقصى سرعة لتنفيذ الشيفرة


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

يمكننا أن ننظر إلى تحسين مشكلة السرعة على مستويين: الإستراتيجية أو التكتيكية.

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

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

و بعملية حسابية ، عن برامج فورتران، أن 4 ٪ من البرنامج تمثل في المتوسط 50 ٪ من وقت التنفيذ. و هذا بدون شك صحيح بالنسبة لجميع اللغات. سنرى كيفية تحسين هذا الوضع.

أولا لنتحدث عن سوء الفهم الشائع على النحو التالي :
"خفض عدد خطوط الشيفرة يحدد حجم وسرعة التنفيذي فيه."

خطأ!

الأدلة ؟

- تهيئة مجموعة من 10 عناصر :
كود :
[align=left][color=Blue]for i := 1 to 10 do MaTable[i] := 0;[/color][/align]

في رأيك، هل الطريقة أسفله ستكون أسرع أم أبطأ ؟
كود :
[align=left][COLOR=Blue]MaTable[1]  := 0;
MaTable[2]  := 0;
MaTable[3]  := 0;
MaTable[4]  := 0;
MaTable[5]  := 0;
MaTable[6]  := 0;
MaTable[7]  := 0;
MaTable[8]  := 0;
MaTable[9]  := 0;
MaTable[10] := 0;
[/COLOR][/align]
باختبار بواسطة دلفي 7 نجد أن الطريقة الثانية أحسن بنسبة أداء بـ 1.7 : 1 (أسرع بـ 1.7 مرة)

واغتنم هذه الفرصة لإبداء تنويه صغير.

التقنيات التي سأتقدم بها لا تشكل الطريقة التي يتعين تطبيقها بصورة عمياء. القليل من هذه التقنيات المطبقة بصورة عامة تصلح لنقلها مباشرة إلى شيفرتك (محتوى برنامجك). سيكون عليك اختبار والتحقق بأن المجمع (Compiler/compilateur) الذي تملكه يتقبلها. وفي الواقع، بعض التقنيات، والتي تظهر سليمة، يمكن لها أن تقلل من قدر الأداء بعد تجميعها. سأوضح بمثال على هذا، وأذكِّر بنقطة هامة جدا: " الاختبار، الاختبار وإعادة الاختبار".
الرد
#3
هناك ست ركائز تذكرها للحصول على الأداء الجيد. هيا! لنضع الأصابع في الشحم
(Allez ! Mettons les doigts dans le cambouis!)


" تبنَّى منطق دلفي "

لا يساورني أدنى شك في أنك تملك قدرا من المنطق. على كل حال .. علينا أن لا نخشى من الزيادة.

على سبيل المثال، فإن التعبيرات المنطقية التالية هي متكافئة:
كود :
[align=center][COLOR=Blue](not A) and (not B)
not (A or B)[/COLOR][/align]
باختيارنا للتعبير الثاني، هو ‘NOT’. الوقت المُوَفَّر بدون شك طفيف، لكن في حلقة طويلة جدا. سوف نرى.

الخروج من الاختبار في الوقت:

هنا مثال لشفرة محسَّنة:
for i := 0 to High( TableTest ) do
if (TableTest < 0) then
NegativeFound := true
وهو حلقة للبحث، حالة شائعة جدا. مبدأ التحسين يرتكز على عدم مواصلة التحقق إذا وجدت النتيجة. لنطبِّق المبدأ:
for i := 0 to High( TableTest ) do begin
if TableTest[i] < 0 then
begin
NegativeFound := true;
;Break
//الخروج حالما وجدت النتيجة
end;
end

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

مثال أخر:
N := Random(101);

if (N>=0) and (N<5) then Categorie := 1;
if (N>=5) and (N<20) then Categorie := 2;
if (N>=20) and (N<101) then Categorie := 3;

و نفس الشيفرة محسنة جزئيا:
if (N>=20) then Categorie := 3
// الخروج حالما وجدت النتيجة
else if (N>=5) then Categorie := 2
// الخروج حالما وجدت النتيجة
else Categorie := 1
نسبة الأداء = 1.3 : 1 ويمكننا أن نحقق أكثر..

ترتيب الاختبارات تصاعديا:
if (N<5) then Categorie := 1
else if N<20 then Categorie := 2
else Categorie := 3
نسبة الأداء = 1.9 : 1

- ستقولون لي : " أين المنطق في كل هذا ؟ "

- حسنا، إنه منطق مجمِّع دلفي 7.

لقد قلت لكم " الاختبار، الاختبار وإعادة الاختبار "

هذا المثال يؤكد أهمية عدم الانسياق وراء نصائح التحسين بدون هدى. ما هو صحيح بالنسبة لـ C# ليس بالضرورة بالنسبة لجافا أو الدلفي. بعض التحسينات صحيحة بالنسبة للغة تتدرج الأداء بوجه كبير من لغة أخرى. بالإضافة، ذلك يمكن أن يختلف من نسخة إلى أخرى لنفس المجمِّع. عليك، إذاً، قياس الأداء لأن قواعد اللعبة تتغير بتغييرك للغة، المجمِّع أو نسخة لنفس المجمِّع، المعالج، الذاكرة الحية، المنطقة (حسنا، حسنا، ربما ليس المنطقة)، الخ..

أقتبس من Olivier DAHAN :
[I]
" لنأخذ التعليمة case كمثال. إلى غاية بورلاند باسكال 7 ترتيب أفضل الثوابت من حيث فعالية الشيفرة هي تلك التي تنخفض فيها وتيرة الاستخدام: حالة الأكثر تكرار يجب أن يوضع في الأول، والأقل تكرارا في الأخير. هذه كانت مرتبطة بشيفرة الآلة التي تولِّدها باسكال (سلسلة من المقارنات والقفز من حالة إلى أخرى ، من الأولى إلى الأخيرة). باسكال غرضية التوجه لدلفي تولِّد شيفرة مختلفة جدا، وهنا إمكانية تحسين الفعالية للتعليمة case وهي وضع ثوابت الحالة في ترتيب عددي تصاعدي (وهو ترتيب الإعلان DECLARATION في النوع إذا كان منتقي الحالة من نوع عددي)".


آمل أنه قد أيقظ الشك لديك.

و إلا سأزيد طبقة:

Case of أفضل من If then else :

عوضا عن كتابة:
case N of
20..100 : Categorie := 3;
5..19 : Categorie := 2;
else Categorie := 1;
end
أفضل الصياغة الأسرع بـ 1.5 مرة:
case N of
0..4 : Categorie := 1;
5..19 : Categorie := 2;
else Categorie := 3;
end

الآن، نسبة الأداء = 1.95 : 1

تقريبا ضعف سرعة المثال في البداية. (إنها تدفنها مرة واحدة، لأن case of دائما أوضح من if then else متداخلة).
- في C#: case of و if then else قابلة للمقارنة.
- على العكس، في الجافا if then else أسرع بـ 6 مرات من case of.
- و في فيسوال بازيك، إنها case of الأسرع بـ 4 مرات من if then else (Steve McConnell dixit).
للمنصت، كيف الحال.

استبدال التعبيرات المنطقية المعقدة بجدول:
على سبيل مثال موجز، لنفرض أن لديكم رقم من الفئة (0،1،2،3) للتخصيص إلى غرض حسب عضويتها إلى مجموعة واحدة
أو أكثر A،Bِ،C :

مثال مقتطف من كتاب Steve McConnell : «CODE COMPLETE» وعُدِّل من C++ إلى دلفي.

على العموم، نكتب على الشكل التالي:
if ((N in EnsembleA) and not (N in EnsembleC)) or ((N in EnsembleA) and
(N in EnsembleB) and (N in EnsembleC)) then Categorie := 1
else if ((N in EnsembleB) and not (N in EnsembleA)) or ((N in EnsembleA) and
(N in EnsembleC) and not (N in EnsembleB)) then Categorie := 2
else if (N in EnsembleC) and not (N in EnsembleA) and not (N in EnsembleB)
then Categorie := 3
else Categorie := 0

بالبحث في جدول، مؤكد سوف لن نزيد من وضوح الشيفرة، لكنه لن يكون أكثر غموضا.. على العموم، يمكننا دائما أن نوثِّق الشيفرة بتعليقات و الجدول سيكون أسهل للتعديل عند الضرورة. يصبح لدينا:
type
TTab = array[0..1, 0..1, 0..1] of byte;
const
TableCategorie : TTab = // notB,notC notB,C B,notC B,C
(((0, 3), (2, 2)), // notA
((1, 2), (1, 1))); // A
Categorie := TableCategorie[Ord(N in EnsembleA),
Ord(N in EnsembleB),
Ord(N in EnsembleC)]

نسبة الأداء = 9 : 1
الرد
#4
تحقق من الحلقات

ضع الاختبارات خارج الحلقات:

من السهل الاهتداء إلى الاختبارات التي لا تُعدَّل داخل الحلقات:

for i := 0 to High(TableTest) do begin
if Choix = 0 then TableTest[i] := TableTest[i] + 1
else TableTest[i] := TableTest[i] - 1;
end

و هي نفسها محسنة:
if Choix = 0 then
for i := 0 to High(TableTest) do TableTest[i] := TableTest[i] + 1
else for i := 0 to High(TableTest) do TableTest[i] := TableTest[i] - 1
نسبة الأداء = 1.35 : 1

التحكم في الحلقات:

هذه التقنية تشبه المثال الأول في هذه المقالة أين سيَّرنا بشكل كامل الحلقة من 10 تكرارات. تطبيقيا، لا يمكن تحقيقه من أجل عدد كبير من العناصر أو عندما تكون هذه الأخيرة غير معلومة. و مع ذلك يمكننا أن نحقق هذه التقنية. هذه حلقة عادية:
i:=0;
while i < High(TableTest) do begin
TableTest[i]:= 0;
Inc(i);
end
و مثال لنفس الحلقة معدلة جزئيا:
i:=0;
while i < High(TableTest)-3 do begin
TableTest[i]:= 0;
TableTest[i+1]:= 0;
TableTest[i+2]:= 0;
TableTest[i+3]:= 0;
inc(i,4);
end

{نضبط الحالات الأخيرة}
if i = High(TableTest)-1 then TableTest[High(TableTest)-1] := 0;
if i = High(TableTest)-2 then TableTest[High(TableTest)-2] := 0;
if i = High(TableTest)-3 then TableTest[High(TableTest)-3] := 0
نسبة الأداء = 1.4 : 1

لكن هذه التقنية لا أحبذها. أولا وجدتها فظيعة. وأيضا، يجب فعلا اختبار زيادة الأداء في كل حالة لأنه يمكن أن تتغير حسب العمليات المنفذة. مجمِّع دلفي يقوم عامة بعمل أحسن من هذا الترقيع. اختبرها ولا تستعملها إلا إذا كانت سرعة التنفيذ مرتفعة.

القيمة الحارسة:

مثال عن حلقة بحث تحتوي على اختبار مركب:
NegativeFound := False;
i := 0;
while (not NegativeFound) and (i < High(TableTest)) do begin
if TableTest[i] < 0 then NegativeFound := true;
inc(i);
end
في هذه الشيفرة، مع انه نخرج في الحين، غير أن كل تكرار يختبر (not NegativeFound) و (i < High(TableTest)).
الاختبار TableTest[i] < 0 وظيفته أن يحدد لنا إذا ما كانت القيمة السالبة قد وجدت. الحلقة، إذاً، تنفِّذ 3 اختبارات في كل تكرار.

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

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

بعض سطور من الشيفرة توضح أحسن من شرح طويل:
TableTest[High(TableTest)] := -1;
كود :
[color=SeaGreen]//القيمة الحارسة[/color]
NegativeFound := false;
I := 0;
while not TableTest[i] < 0 do inc(i) ;  
[COLOR="SeaGreen"]// نخرج
{ و نتحقق إذا ما قد  وجدت القيمة}[/COLOR]
if i < High(TableTest) then NegativeFound := true[/align][/COLOR]
[color=Red]نسبة الأداء = 1.7 : 1

ضع الحلقة الأكثر نشاطا في الداخل:

عندما تكون الحلقات مركبة، فكر في أي الحلقات ستضعها خارجا وأيها ستضعها في الداخل. المثال التالي قابل للتحسين:
[align=left]for Col := 0 to 999 do
for Ligne := 0 to 1 do Total := Total + MaTable[ Col, Ligne ];

الحلقة الخارجية تتكرر 1000 مرة. الحلقة الداخلية تتكرر 2 × 1000 = 2000 مرة. إذا لدينا المجموع 3000 تكرار.
نعكس الحلقات:
for Ligne := 0 to 1 do
for Col := 0 to 999 do Total := Total + MaTable[ Col, Ligne ]
نسبة الأداء = 1.9 : 1

في الشيفرة المحسنة الحلقة الخارجية تنفذ مرتين. الحلقة الداخلية تنفذ 2 × 1000 = 2000 مرة. إذا لدينا المجموع 2002 تكرار.
الرد
#5
" حذار من المعطيات التي تتعامل بها "

هذه بعض السطور التي غالبا ما نجدها ضمن شيفرة التي تظهر رسوما متحركة على الشاشة، مثلا:
كود :
[COLOR=Blue]Var X, Y, Angle, Hypot : Smallint;
for Angle := 0 to 360 do begin
       X := Round( cos(DegToRad(Angle)) * Hypot );
       Y := Round( sin(DegToRad(Angle)) * Hypot );
end;
[/COLOR]
احترس لإجراءات النظام:

أولا، الوحدة Math تمكننا من استعمال الإجراء ()SinCos الذي هو أسرع مرتين من مناداة ()Sin متبوعة بـ ()Cos:
كود :
[COLOR=Blue]Var X, Y, Angle, Hypot : Smallint
Sinus, Cosin : Extended;
for Angle := 0 to 360 do begin
         SinCos(DegToRad(Angle) ,Sinus, Cosin);
         X := Round( Cosin * Hypot );
         Y := Round( Sinus * Hypot );
end;
[/COLOR]
نسبة الأداء = 1.3 : 1

DegToRad أوضح وأفضل لقراءة الشيفرة، لكنها تأخذ الكثير من الوقت للتنفيذ. ننزعها و نقوم بالتالي:
كود :
[COLOR=Blue]for Angle := 0 to 360 do begin
     SinCos(Angle*0.0174532925199433 ,Sinus, Cosin);
     X := Round( Cosin * Hypot );
     Y := Round( Sinus * Hypot );
end;[/COLOR]
نسبة الأداء = 1.5 : 1 (بالنسبة للمثال الأول)

المعطيات المخبأة:

سرعة الإجراء ()SinCos ليس بسرعة استعمال الجدول. إن تقنية تخبئة المعلومات تعتمد على حفظ - بصورة نظامية - القيَم المستعملة بكثرة في الذاكرة. هنا سنخزن القيَم المثلثية في الجدول:
كود :
[COLOR=Blue]Var //متغيرات عامة
         MonCos : array[0..360] of Extended; // جدول مخبأ
    MonSin : array[0..360] of Extended; // جدول مخبأ

procedure TForm1.FormCreate(Sender: TObject);
var Angle : Integer;
         Sinus, Cosin : Extended;
begin
for Angle := 0 to 360 do begin
    SinCos(Angle*0.0174532925199433 ,Sinus, Cosin);
    MonSin[ Angle ] := Sinus; // إنشاء جدول مخبأ
    MonCos[ Angle ] := Cosin;
end;
...
for Angle := 0 to 360 do begin
         X := Round( MonCos[ Angle ] * Hypot );
         Y := Round( MonSin[ Angle ] * Hypot );
end;
[/COLOR]
نسبة الأداء = 7 : 1 (بالنسبة للمثال الأول)

وحدة المعالجة المركزية محسَّنة من أجل 32 بيت:

بدون شك لاحظت أننا عملنا بـ SmallInt في حلقة الحساب. هذا مبرر لأنها كافية لحساب إحداثيات الشاشة. في حين، وحدة المعالجة المركزية تعمل براحة كبيرة عندما تتعامل مع Integer. التعديلات بسيطة:
كود :
[COLOR=Blue]Var X, Y, Angle, Hypot : Integer;
Sinus, Cosin : Extended;[/COLOR]
نسبة الأداء = 9 : 1 (بالنسبة للمثال الأول)

ضبط الزائد عن الحاجة لإجراءات النظام:

نعم في الحقيقة نحن نعمل على الشاشة.

إنها قيمة مثلثية من Extended أي ( 15رقما بعد الفاصلة) تضبط عملية إنزال رجل على القمر، بالنسبة لشاشتي 'm….' لست بحاجة لمثل هذه الدقة. سنقلل من دقة جداول المعطيات المثلثية المخبأة.

و مثلما رأينا أن وحدة معالجة المعطيات تحبذ 32 بيت. إذن و في نفس السياق نحول extendeds إلى Integers.

و في طريقنا نحذف Round، إجراء تابع للنظام مكلف أيضا.
كود :
[COLOR=Blue]Var // متغيرات عامة
MonCosInt : array[0..360] of Integer; // جدول مخبأ
    MonSinInt : array[0..360] of Integer; // جدول مخبأ
procedure TForm1.FormCreate(Sender: TObject);
var Angle : Integer;
Sinus, Cosin : Extended;
begin
for Angle := 0 to 360 do begin
    SinCos(Angle*0.0174532925199433 ,Sinus, Cosin);
    MonSinInt[ Angle ] := Round( Sinus * 1000 );
    MonCosInt[ Angle ] := Round( Cosin * 1000 );
end;
...
for Angle := 0 to 360 do begin
X := MonCosInt[ Angle ] * Hypot div 1000;
Y := MonSinInt [ Angle ] * Hypot div 1000;
end;
[/COLOR]
نسبة الأداء = 300 : 1 (بالنسبة للمثال الأول)

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

تفطَّن لكل شيء:

في رأيكم، ما المزعج في الشيفرة التالية:
كود :
[COLOR=Blue]Hypothenuse1 := Sqrt( Sqr(CoteA1) + Sqr(CoteB1) );
Hypothenuse2 := Sqrt( Sqr(CoteA2) + Sqr(CoteB2) );
if Hypothenuse1 < Hypothenuse2 then {افعل الأتي}; [/COLOR]
بكل بساطة إذا Hypothenuse1 < Hypothenuse2 إذن
CoteA1 + CoteB1 < CoteA2 + CoteB2
يمكننا أن نتجنب تكلفة ()Sqrt و ()Sqr عبر التالي:
كود :
[color=Blue]if CoteA1 + CoteB1 < CoteA2 + CoteB2 then {افعل الأتي};[/color]
نسبة الأداء = 10 : 1
الرد
#6
" استعمل SCANLINE "


إذا كانت Canvas.Pixelsملائمة تطبيقيا لمعرفة لون بيكسل منفرد، في حالة ما إذا كنا نعمل على كامل
سطح Bitmap، يجب استعمال Scanline التي هي أكثر فاعلية. في الواقع، فإن الاختناقات المتعلقة بوقت التنفيذ تتواجد غالبا في معالجة Bitmaps.

أوجهكم إلى المثال الجيد الذي قام به Florenth الذي يبدو أنه قام بدراسة المشكلة عدة مرات.
http://www.delphifr.com/codes/BON-USAGE-...43222.aspx
الرد
#7
" تيقظ للأفكار المتلقاة "


مثال: الإزاحة:

كثيرا ما نرى ونسمع أن الإزاحات المزدوجة (Binaires/Binary) سريعة جدا إذا ما أردنا استبدال عملية ضرب أو قسمة بـ 2، 4، 8 الخ:
X := X shl 1
Y := Y shr 2
مع ذلك فوقت التنفيذ هو نفسه بواسطة دلفي 7. إذن نفضل الوضوح:
X := X * 2
Y := Y div 4
نسبة الأداء = 1 : 1

طلبت توضيحا من f0xi الذي يظن أن مجمِّع دلفي ممتاز جدا. هذا هو رده:

" لاسيما وحدات المعالجة المركزية التي أصبحت جيدة.
في حقبة المعالجات وحيدة القلب (monocore)، استعمال shr 1 أو shl 1 أسرع من عملية الضرب أو القسمة. الآن مع وحدات المعالجة مزدوجة (dual)، رباعية (quad)، ثمانية القلب (octo-core)، أصبح سخيف هذا النوع من التحسين.
[ ]
التحسين "المحلي " ليس في الحقيقة سؤالا يُطرح، نحن نتحدث أكثر عن التحسينات " العامة " لمجموع البرنامج و عناصره و أكثر عن منهجية العمل، لأنه إذا كان باستطاعة المجمِّع أن يحسِّن بعض الأوامر ،لا زال غير قادر على أن يحسن مجموعة كاملة من الأوامر."
الرد
#8
" تجنب الكمال "


التحسين، و الأمثل، أحد هذين اللفظين لا يبدو لك معقولا ؟ ( ;

البرنامج هو توازن هش بين وضوحه، سهولة صيانته، وسرعته، و حجمه، و دقته، الخ.

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

الخاتمة:

تعلم استعمال هذه التقنيات عن دراية. في حال تحسين شيفرتك، لا تتوانى عن أن تترك تعليقا عن التقنية التي استعملتها. على العموم إذا كانت التقنيات المستعملة هنا لا تزال صافية، ستكون معيار للبرمجة، لا ؟
يوجد بكل تأكيد تقنيات أخرى أقل أو أكثر فاعلية التي تساعد على تجنب الجداول متعددة الأبعاد إلى غاية استعمال لغة التجميع Assmebler (التحسين في النهاية هو نفسه في لغة التجميع، أوجهكم إلى هذا الموقع http://www.fastcodeproject.org للحصول على أحسن الإجراءات). لكن هدف هذه المقالة وهو وضعكم على الطريق السوي، وليس إنشاء قائمة فريدة للتقنيات.
وعندما يكون في استطاعتكم مضاعفة سرعة تنفيذ شيفرة إلى 300، ستكونون سعداء أنكم فعلتموها ..
....
شكرا لكل من ساعدني أو شجعني على كتابة هذه المقالة.
انتهت الترجمة
الرد
#9
في الأخير أذكر أنه إذا كانت هناك تعليقات فلا بد من ذكرها

كما انني لم أترجم تعليقات القراء (التي هي بنظري مهمة) وأتركها لمن يريد ترجمتها

المعذرة لأنني لم أرفق الملفات في أول مشاركة (نسيت :o)


يمكن للمشرف أن ينقلها لأول مشاركة

تحياتي Smile


الملفات المرفقة
.pdf   TACTIQUES AR (0.1).pdf (الحجم : 279.97 ك ب / التحميلات : 265)
.pdf   TACTIQUES FR.pdf (الحجم : 93.32 ك ب / التحميلات : 146)
الرد
#10
الله يجازيك كل الخير اخي مروان Smile
تنسيق PDF احسن بكثير...
اذا كان لديك الوقت اخي ان تدعم الترجمة بامثلة تطبيقية بملفات مصدرية...

تحياتي
الرد


التنقل السريع :


يقوم بقرائة الموضوع: بالاضافة الى ( 1 ) ضيف كريم