הבלוג של ארתיום
בלוג על לינוקס, תוכנה חופשית, מוזיקה, סלסה, ומה לא!
מאמרים בנושא פיתוח.
למה נטשתי את Boost אפילו שתרמתי אליו שתי ספריות בעבר
בעבר השתמשתי הרבה ב־Boost לטובת פרוייקטים שונים ב־C++. במיוחד לפני ש־C++11 הפך לנורמה. אבל לאט־לאט עם בעיות שבירת API השונות התחחתי להתרחק ממנו במיוחד כש־C++11 ויותר נתן מענה למרבית הבעיות הקריטיות ש־Boost פתר בעבר.
אז שנים רבות הסתדרתי בלי Boost. אפילו שתרמתי שתי ספריות בעבר Boost.Locale ו־Boost.Nowide - הן עכשיו מתוחזקות בצורה יוצאת דופן ע"י מפתח אחר.
עכשיו אני עובד על פרויקט גדול OpenLiveStacker שגם בו לא השתמשתי ב־Boost וגם היה לי מענה לבעיות נוספות דרך CppCMS שאני משתמשו בו בפנים לטובת UI. הוא מיועד בעיקר לאנדרואיד ולינוקס אבל הבנתי שיהיה שימושי גם בחלונות ואז התחלתי לעשות הסבה לחלונות.
בגדול הקוד גם ככה היה כמעט ולא תלוי בפלטפורמה אז לרב זה היה חלק ואז הגעתי לבעיה פשוטה של להריץ תהליך חיצוני, להרוג אותו אם צריך, לקבל סטטוס. בלינוקס ואנדרואיד פשוט עשיתי fork/exec/kill/wait. ואז הגעתי לחלונות. טוב אז מה עושים? אמרתי למה להמציא גלגל פשוט אקח Boost.Process - גוגל זריז - הוא בדיוק נותן מענה למה שאני צריך. אולי הייתי צריך להשתמש בו מלכתחילה? טוב נו. הסתכלתי במדריכים כתבתי, הורדתי גרסה אחרונה 1.88 של Boost לחלונות מקמפל ו־... לא עובד.
השגיאה bp::child לא מוגדר! טוב מוודא שאני פותח את הגרסה אחרונה של התיעוד (גוגל לא תמיד מביא אותה) והפלא הפלא אין יותר bp::child יש bp::process! מה קרה? אכן API השתנה. מתי זה קרה? לפני כשנה באוגוסט 2024. כלומר אם הייתי משתמש ב־Boost.Process מלכתחילה הקוד היה נשבר. (כדי להשתמש ב־api ישן צריך לעשות include וליצור aliases וכד)
שורה תחתונה - הם שברו API לגמרי. לא הוסיפו API חדש עם bp::process אלא מחקו את הקיים והחליפו. זה הזכיר לי לגמרי למה הפסקתי להשתמש ב־Boost. אז עשיתי אחורה פנה, ופשוט תחת ifdef כתבתי קוד עם שימוש ב־CreateProcess של חלונות ו... זה זה עבד ללא דופי.
עצוב. איך מפתחי תוכנה פשוט לא מבינים את המשמעות של תאימות API לאחור.
שבירת API בלי סיבה מוצדקת זה פשע נגד הקהילה
באתי לבנות את הפרויקט שלי OpenLiveStacker עם OpenCV אחרון 4.11 - הכל נופל. נעלמו אופרטורים +/- על פעולות וקטוריות. לדוגמה הקוד הבא:
cv::v_float32x4 zero = cv::v_setall_f32(0.0f);
cv::v_float32x4 one = cv::v_setall_f32(1.0f);
int limit = N/4*4;
for(;i<limit;i+=4,p+=4,d+=4,f+=4) {
cv::v_float32x4 v=cv::v_max(zero,cv::v_load(p) - cv::v_load(d));
v = cv::v_min(cv::v_load(f) * v,one);
cv::v_store(p,v);
}
פשוט לא מתקמפל כי הסירו אופרטורים של חיבור/חיסור. למה? כובע!
איזו זאת יש לכם לשבור את הקוד של האחרים ועוד בפרויקט ענק שמשתמשים בו בכל העולם ועוד בלי סיבה אמתית.
טוב, נחכה ונראה
איך ללמוד תכנות בגיל צעיר?
כשהייתי בן 11 הורים שלי קנו לנו מחשב קטן ZX Spectrum עם מעבד Zilog Z80 מ־48KB של זכרון. "מערכת ההפעלה" שלו הייתה BASIC פשוט, הוא התחבר לטלוויזיה, התוכנה נשמרה ונטענה מקלטות. אומנם קיבלנו את המחשב בתחילת שנות ה־90 אבל בפועל זו הייתה טכנולוגיה של שנות ה־80. כך או אחרת זה הדליק את העניין שלי ושל אחי בתוכנה התווה את הדרך המקצועית של שנינו. למדתי עליו תכנות בסיסי והאסמבלי של Z80 הוא הראשון (ובעצם היחיד) שלמדתי לעומק.
קצת נוסטלגיה
עבר המון זמן. אבל תמיד אהבתי את המחשב הקטן ההוא. שחקתי עם אמולטורים שלו כמו fuse ואפילו בניתי תוכנה עבורו. אפילו חשבתי לקנות אחד ישן - אבל תמיד זה העלה שאלות - חיבור למסכים, אלטרוניקה של שנות ה־80 עם קבלים שלרוב נהרסו ועוד כל מיני שיקולים.
אבל לאחרונה יצאה מחשב "מחודש" הנקרא "The Spectrum" שמעשה מדמה את המחשב הישן נראה בדיוק כמוהו אבל עובד עם טכנולוגיה מודרנית - מאפשר לטעון טכנה מדיסק־און־קיי ומתחבר למסך עם HDMI. אחרי הרהורים קצרים הזמנתי אחד מ־Amazon צרפת ו... לא התאכזבתי. באמת, מחשב קטן וגאוני. מהר מאוד כתבתי בשבילו כמה משחקים פשוטים ב־BASIC למשל Snake. הראיתי את המחשב לבתי הגדולה. הראיתי כמה פקודות פשוטות. כתבתי לידה משחק פשוט בו תפוסים קוביה שנופלת
1 BORDER 1
5 LET row=0
6 LET score=0
10 LET p=16
20 LET col=15
25 LET row=0
30 PRINT AT row,col;"#"
40 LET row=row+1
100 PRINT AT 20,p;"^"
105 LET psave=p
110 IF INKEY$="p" AND p<31 THEN LET p=p+1
120 IF INKEY$="q" AND p>0 THEN LET p=p-1
130 IF psave<>p THEN PRINT AT 20,psave;" "
140 PRINT AT row-1,col;" "
145 IF row>20 AND p=col THEN LET score=score+1: PRINT AT 21,0;"Score ";score;
150 IF row>20 THEN LET row=0: LET col=INT (16*RND)+7
200 GO TO 30
הפתיעה אותה כמה קל זה היה אז במחשבי 8bit הפשוטים לכתוב דברים כאלה. הייתי רוצה לתת גם לילדים שלי להיחשף לעולם התוכנה. ולמרות שברור לי מחשב כזה הוא נפלא למשימות האלה, אני לא חושב שזה רעיון טוב ללמיד את הטכנולוגיה של שנות השמונים.
אז מה האלטרנטיבות הים?
אני רציתי סביבה בה אפשר לבנות דברים פשוטים כאלה בלי "לפתוח חלונות" לטפל באלף הגדרות ממשק וכד'. משהו שלילד (וגם מבוגר) יהיה קל וכיף להיכנס.
לפני שתגידו Scratch - אני מכיר - אבל הבעיה שלי עם Scratch ש"שפת התכנות" מזעזעת. לא הצלחתי להתחבר. וגם כשנתתי לבתי הגדולה היא לא המשיכה הרבה עם זה. אולי בגלל שאני גם לא הצלחתי.
פתחתי דיוק בנושא בקבוצת פייסבוק של משתמשי ZX Spectrum שוודאי יבינו את הכוונה שלי:
- שפת תכנות קלה יחסית
- אפשרות הפעלה של הכל דרך ide (שלא אצטרך ללמד גם שורת פקודות)
- קל מאוד להגיע לתוצאות מהירות
ועלו מספר אפשרויות:
- love2d עם Lua
- pygame-zero עם Python
- processing עפ שפת תכנות מבוססת Java
- כמובן אותו ה־Scratch
התחלתי לחקור ופתחתי פרוייקט שכולל קוד המקור של כולם (מלבד Scratch)
מטרה - לכתוב משחק פשוט בו כדור נופל ממקום אקראי ומנסים תפוס אותו עם המשטח שמזזים אותו בעזרת מקשים. אם תופסים הניקוד עולה ומוצג למשתמש. הנה דוגמה של המחשק שבניתי ב־pygame zero:
תמיכה בחצובה או סיפורי הסבת indi ו-indigo לאנדרואיד
מה שטוב בסטנדרטים זה שיש הרבה כאלה...
אחרי תקופה ארוכה של פיתוח תוכנה/אפליקציית OpenLiveStacker המיועדת לצילום אסטרונימי בזמן אמת, הגעתי לנקודה שמעבר לתמיכה במצלמה נדרשת תמיכה בחצובה ובמצלמה גנרית. אז איך מתחברים במשהו גנרי? משתמשים בממשק סטנדרטי! בעולם "חלונות" יש ASCOM. בעולם הלינוקס המצב נותן מגוון רחב של סטנדרטים
המשך...למידת מכונה פתוחה באמת, האם אני נלחם בקרב עבוד מראש?
לפני מספר שנים התחלתי פרוייקט dlprimitives - המימוש הבסיסי של פעולות Deep Learing ב־OpenCL. והמשכתי לתמיכה ב־OpenCL ב־pytorch. אני ממשיך לפתח את המודול של PyTorch על אש קטנה והאמת, הגעתי לביצועים מרשימים גם עבור כרטיסי nvidia וגם amd.
למה בעצם אני משקיע את זמני בזה:
- קודם כל, כל תעשיית ה־deep learning היום מבוססת על דברים סגורים. למרות שהכלים כמו pytorch הם פתוחים לחלוטין - למטה יושב הקוד של cudnn ששמור בכספת.
למרות שיש עוד 2 שחקנים רציניים בשוק כרטיסי המסך (AMD ולאחרונה גם Intel) והקוד שלהם פתוח - כל אחד ממציא גלגל מחדש ועושה משהו משלו. למעשה אין שום דבר משותף בין הקוד שלהם. אם אני רוצה לשפר טכניקה קיימת או להביא איזה כלי חדש אני נתקל בבעיה רצינית:
- אני חייב לשפר משהו שאין לי גישה אליו (cudnn) וזה מאוד קשה.
- אם זה תופס צריך למעשה מספר מימושים לכל אחת מהפלטפורומ האלה.
- אם מישהו רוצה להשתמש במודלים מאומנים - המימוש הוא תלוי חומרת המשתשת - למעשה צריך לתמוך בכל תשתית בנפרד nvidia-cuda, amd-rocm, intel - xpu וב־apple עוד איזו שטות - כמובן אין שום הבטחה שזה למעשה יעבוד בכל מקום.
אז אני עובד על משהו שעובד על כולם OpenCL וגם מגיע בין 60% ל־80% ממה שאפשר הגיע עם המימוש המקורי (שזה cuda/rocm).
אני ממשיך לראות את amd משפרים את rocm מצד אחד (לפי שבוע התקנתי pytorch rocm על אובונטו 24.04 בצורה יחסית חלקה וזה פשוט עובד) ומצד שני הורסים אותו - כי מוציאים תמיכה בכרטיסי ישנים ותומכים באופן רשמי רק בדברים ייעודיים. למעשה rx6600xt של גם לא נתמך באופן רשמי וצריך להשתמש במשתנה סביבה שיתייחסו אליו כמו לכרטיס הנתמך
אני רואה ש־intel גם הולכים בכיוון זה ועל פניו אפשר גם לאמן היום על הכרטיסים שלהם. אבל הם מסתמכים על על טכנולוגיה נוספת שעוד פעם לא תואמת לשום דבר אחר.
כל ההשקעות של Intel ושל AMD הן למשהו מידי שיעשה טלאי אבל לעולם לא יפתור את הבעיה האמתית של העולם ה־DL.
לכן, אני ממשיך לעבוד ורואים שהחברות האלה ממשיכות לבזבז משאבים על משהו שלא באמת עוזר מלבד לאלה שנתקעו עם מסך amd/intel וגילו שאולי גם בא להם לאמן רשתות ניירונים. ברור לכם שהם יתייאשו תוך כלום זמן ופשוט יקנו כרטיס טוב של nVidia שבאמת יעבוד כמו שצריך.
טוב, נו. אני לפעמים מנסה להרים פרוייקטים שנראים בלתי אפשריים. האם זה יצליח? לא יודע - המשאבים שלי מוגבלים: שעה־שעתיים כמה פעמים בשבוע כשאני לא עסוק בדברים אחרים. אם היה לי צוות של 5-6 מפתחים שעובדים על זה במשרה מלאה - ללא ספק זה היה מצליח. אבל אין לי משאבים כאלה.
מצד אחד אני נהנה מהצלחות קטנות - באמת, המפתחים של pytorch מאוד עוזרים. ובכל פעם זה מתקדם והופך לקל יותר להתקין או להשתמש בזה. מצד שני לפעמים זה מייאש כמה עבודה יש לי וכמה השחקנים הרציניים - האלה עם הכסף עושים שטויות גמורות במקום לשתף פעולה (אגב למען האינטרסים שלהם)
ועכשיו שאלה: מכירים שירות ענן שמאפשר לבנות חבילות ל־pip (רצוי גם לחלונות)