كيف اكتب دالة سريعة التنفيذ ؟
#1
السلام عليكم ورحمة الله وبركاتة
كأحد مميزات البرامج المهمة هي سرعة تنفيذ البرنامج ..
والتي أتجاهلها كلياً عندما اقوم بكتابة برامجي للاسف الشديد
فكل إهتمامي ينصب على اني اطبق الفكرة مهما كانت الوسيلة


سؤالي كتالي :
كيف أكتب دالة سريعة التنفيذ ؟
بغض النظر عن ترتيب الكود او سهولة قرائتة

وحبذا تكون آلية الجواب .. مثلاً ...
1 استعمل المؤشرات .. مثال بسيط على ذلك(المؤشرات)
الرد
#2
وعليكم السلام ورحمة الله وبركاته

ألق نظرة عميقة على مشروع Fastcode
http://delphi4arab.net/forum/showthread.php?tid=3008
ايضا موضوع
قياس الزمن
http://delphi4arab.net/forum/showthread.php?tid=2748
الرد
#3
سبق وأن اطلعت على تلك المواضيع

لكن حبذا ذكر الخلاصة ... على شكل نقاط إن لم يكن هناك مانع
نلتقي لنرتقي
الرد
#4
الخلاصة : تسريع دالة بمعالج ما
تفهم جيدا كيف يعمل ذلك المعالج
تكتب الدالة بالتجميع Assembly
تعمل لها optimization لتستفيد من ذلك المعالج
ان كان ولا بد (كي يعمل برنامجك على كل الاجهزة) تكتب أيضا البديل في حالة وجود معالج اقدم

مرجعين الاستزادة (ان لم تكن سبق وان اطلعت عليهما)
agner.org/optimize
mark.masmcode.com
الرد
#5
الأمر متعلق بنوع المعالج الذي تستهدفه ..
+ليس شرط أن تستخدم الأسمبلي .
الموضوع طويل جدا .. سأحاول أن أذكر الأشياء المهمة فقط :

- عليك بتجنب استعمال الحلقات و جمل الشرط :
PHP كود :
function BoolToStr(Value: Boolean): PChar;
begin
  
if Value then
    Result 
:= 'True'
  
else
    
Result := 'False';
end;

function 
FastBoolToStr(Value: Boolean): PChar;
const
  
Table: array [Boolean] of PChar = ('False', 'True');
begin
  Result 
:= Table[Value]
end; 
- محاذاة البيانات data alignment .
PHP كود :
type
  TRec 
= record
    B1
: Byte;
    
B2: Byte;
    
B3: Byte;
  
end;

  
TFastRec = record
    B1
: Byte;
    
B2: Byte;
    
B3: Byte;
    
Reserved: Byte;
  
end; 
- تمرير المتغيرات بالمرجع في حال لن يتم تعديلها .
PHP كود :
function GetStr(S: string): string;
begin
  Result 
:= 'Hi ' + S;
end;

function 
FastGetStr(const S: string): string;
begin
  Result 
:= 'Hi ' + S;
end;

function 
FastGetStr2(var S: string): string;
begin
  Result 
:= 'Hi ' + S;
end; 
بهذه الطريقة .. لن يتم نسخ هذه البيانات داخل ال stack !
- محاذات عنوان القفز في الجمل الشرطية (يمكن عملها بالأسمبلي فقط)
PHP كود :
procedure do_asm;
asm
  cmp eax
,eax
  je 
@@nn
  
{ use n(nop) to align dest address ! }
  
nop
@@nn:
end; 
- استخدام جمل تحقق بدون if :
PHP كود :
function IsNeg(value: integer): Boolean;
begin
  
if value < 0 then
    Result 
:= True
  
else
    
Result := False;
end;

function 
FastIsNeg(value: integer): Boolean;
begin
  Result 
:= (value < 0)
end; 

عند استخدامك لهذه الطريقة فسيقوم الكومبايلر باستخدام التعليمة SETcc/CMOVcc بدون تعليمة قفز !
ركز جيدا عليها Smile

- استخدام تعليمات معينة بدل التعليمات التي يستخدمها الكومبايلر :
كمثال .. لو لديك بيانات بطول 64 بت فالأفضل ان تستخدم mmx على 32 بت .
أما على 64 بت .. فحجم المسجلات بالفعل 64 بت .. لذلك لن تكون بحاجة الى استخدام الاسمبلي .

-استخدام ال inline للدوال الصغيرة :
PHP كود :
function GetLowWord(W: Word): Byte;
begin
  Result 
:= W and $FF;
end;

function 
FastGetLowWord(W: Word): Byte; inline;
begin
  Result 
:= W and $FF;
end; 

بهذه الطريقة لن يقوم الكومبايلر باضافة call الى الدالة .==> أداء أسرع ..
العيب : ستواجه مشكلة في بعض الحالات (عند debuging)
عن نفسي : لا أستخدمها عند ال debug :

PHP كود :
function FastGetLowWord(W: Word): Byte;{$IFNDEF DEBUG} inline;{$ENDIF} 

-استخدام ال Bit manipulation بدل التعيمات الأخرى :
كمثال :
هذا كود بسيط يقوم بتقريب عدد الى مضاعف 4 .. بحيث يكون ناتج القسمة على 4 = 0

PHP كود :
function RoundTo4(Value: Integer): Integer;
begin
  Result 
:= Value;
  if 
Result mod 4 <> 0 then
    Result 
:= ((Value div 4) * 4) + 4;
end;

function 
FastRoundTo4(Value: Integer): Integer;
begin
  Result 
:= (Value + 3) and (not 3)
end; 

الدالة الأولى بطيئة .. ليس فقط لاستخدام if بل لأنه معروف أن التعليمة div من أبطأ تعليمات الأسمبلي .

[COLOR="red"]-مع دلفي xe7 يمكنك استخدام parallel library :
تسمح لك هذه الطريقة بمعالجة العديد من التعليمات في نفس الوقت ..
كمثال :
لديك مجموعة من السطور (نص) ستقوم باجراء بعض التعديلات عليه .
لو كان في المعالج الذي تستخدمه نواتين .. فسيتم استخدامهما في نفس الوقت بحيث .
النواة الأولى تقوم بمعالجة السطر n .
و الثانية ستقوم بمعالجة السطر n+1 .
النتيجة : أداء سريع بنسبة optimisation تصل الى 40 % أو أكثر .

[/COLOR]
-.... العديد من الأمور ..

ان كان ليد بعض الوقت فعليك بالاطلاع على : Intel® 64 and IA-32 Architectures Optimization Reference Manual
كود :
http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-optimization-manual.html الكتاب يستهدف معالجات انتل فقط .
الكتاب بالفعل جد رائع .. لقد سبق و اطلعت عليه ..
يشرح الطرق السليمة لكتابة أكواد سريعة .
Open Your Source .. Open Your Mind
الرد
#6
شكراً لك أخي SMP3 و B.M.AbdelAziZ

نعم هذا ما كنت أقصد بالسؤال .. بعض الـ Tricks والطرق التي تجعل الكود أسرع
أجابة شافية ووافية أخي SMP3
نلتقي لنرتقي
الرد


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


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