על מופלאות ה-abs?

erezsh

New member
על מופלאות ה-abs?

בהשראת הזמן הפנוי שיש לי כתוצאה מהשפעת המודרנית והשפעותיה, החלטתי לתזמן כמה דברים. רשמתי את הקוד הבא:
long clk; unsigned cnt=1000000000L; int sum=0; randomize(); clk = clock(); for(c=0;c<cnt;c++) { sum-=5; //to make it less cachable sum=abs(sum); //*1 //sum=(sum>=0)?sum:-sum; //*2 } clk=clock()-clk;​
הרצתי את הקוד, פעם אחת עם abs - *1, ופעם אחת עם תנאי רגיל - *2, גם עם וגם בלי אופטימיזציה, התנאי הרגיל תמיד היה מהיר יותר . נשמע לכם הגיוני??
 

eyalbd

New member
כן נשמע הגיוני

כי בקומפיילר שלך abs הוא כנראה לא inline ואז יש קריאה לפונקציה. בGCC למשל זה לא כך.
 

eyalbd

New member
אפשר לבדוק ע"י קומפיציה לאסמבלי

תבדוק את זה:
#include <stdlib.h> int my_abs1(int a) { return abs(a); } int my_abs2(int a) { return a < 0 ? -a : a; } // Use this command for compilation // // gcc -S -O2 my_abs.c // // then look at my_abs.s​
 

DNile

New member
ותנסה גם את זה:

mov ax, sum; mov cx, cnt; forloop: sub ax, 5 cwd xor ax, dx sub ax, dx loop forloop וגם: mov ax, sum; mov cx, cnt; forloop: sub ax, 5 notneg: neg ax js notneg; loop forloop​
 

voguemaster

New member
וכמובן

שאם אנחנו פדנטיים וכבר מנסים לעבוד עם אסמבלי כדי להרוויח ביצועים אולי כדאי שגם נעשה את זה כמו שצריך. לדוגמא פקודת ה-LOOP היא פקודה בזבזנית שתמיד לוקח לה יותר זמן לביצוע מאשר צמד הפקודות dec ו-jz.
 

erezsh

New member
תודה, אבל אני מכיר את הטריק באסמבלי

הרעיון הוא לעשות את זה עם C.
 

DNile

New member
הרעיון ידידי,

הוא שאתה משתמש בפונקציית ספריה, שיכולה להיות ממומשת איך שבא לה. מקרה אחד למשל הוא פשוט לממש את הפונקציה הזאת בתור הטריק הנ"ל באסמבלי, כפונקציית אינליין, ועם מספיק אופטימיזציות, הקוד שנתתי לך בהחלט יכול להווצר ככה.
 

גיל14

New member
קוד Portable הוא מוגבל מבסיסו.

לך תדע באיזה קומפיילר מישהו יקמפל את זה, והאם _שם_ Abs() יותר מהירה.
 

גיל14

New member
אולי אני קצת (מאוד) חדש לאסמבלי...

אבל בראשון - הכנסת ערך בdx לפני שאתה משתמש בו ככה? קשה לי לדעת מה אתה עושה בלי כל ההערות שהורגלתי לכתוב... בספר של ג'ף דנטמן כתוב שאם תשתמש ישירות בeax במקום בax זה יהיה יותר מהיר. לתשומת לבך.
 

erezsh

New member
How sweet..

למען האמת אתה צודק גיל, eax יותר מהיר במעבדים החדשים. ואתה גם צודק בקשר לאתחול dx. ברפרוף קל מאוד הייתי מהמר שהוא שכח איזה sbc edx,edx...
 

גיל14

New member
Baa. אתם צודקים.

אני עדיין לא רגיל שאין הערות. ואז אני צריך ללכת לחפש מה בדיוק CWD עושה. If the sign bit in AX is 1, then this instruction will set all bits in DX, making them all 1 (negative number); and if the sign bit in AX is 0, it will clear all bits in DX, making them all 0. כמה מאוד נחמד..
 

erezsh

New member
עכשיו אני בכלל מבולבל:

>gcc -O1 try.c >a Result = 0 Clocks: 3515, Secs: 3.515000 >gcc -O2 try.c >a Result = 0 Clocks: 4616, Secs: 4.616000 >gcc -O3 try.c >a Result = 0 Clocks: 4346, Secs: 4.346000​
?!?!?!?!?!!?!?!?!? !?!?!?!?!?!!?!??!!
 

erezsh

New member
וזו לא טעות במדידה שלי

הקוד שנוצר ע"י O1 הוא יעיל יותר (jump אחד פחות בלולאה ופחות שימוש ב-RAM).
 

DNile

New member
קדימה ארז!

be a man... זוכר את הסרט הזה? תקלה מופלאה נראה לי שקראו לזה.. הרובוט ההוא שקיבל חיים משל עצמו, ואז רצו לפרק אותו, והוא רק בוכה כל הזמן: No disassemble(בקטע של - אני לא רוצה למות). אז אתה יודע מה? אנחנו לא בסרט הזה :) וdisassembly אין משמעו מוות. אז לך על זה. תסתכל בקוד אסמבלי שנוצר, והבלבול יעלם.(בלבול אמרתי, לא בולבול לכל הנחרדים).
 

erezsh

New member
No disassembly, no!

הקטע האהוב עליי בסרט. התסכלתי בקוד. כשהייתי בכיתה ט' יכולתי לכתוב קוד יותר יעיל - הוא קופץ פעמיים רק בשביל לעשות neg. הוא קורא על פעם מחדש את הערך 5 ואת הערך 1000000 (!) כשיש לו את ecx ו-edx פנויים לגמרי. וזה ב-O3!
 
למעלה