מאמרים בנושא ‏C++‎‏‏.

לחבר שני תחביבים

ב־יום חמישי, 13 באפריל 2023, מאת ארתיום; פורסם תחת: תכנה חופשית, לינוקס, פיתוח, תכנה ומחשבים, CppCMS, C++‎‏, אסטרונומיה; ‏0 תגובות

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

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

אמרנו לינוקס?

אז מה המצב התוכנה בתחום זה מבחינת תוכנה חופשית ולינוקס? יש ויש. חלק הארי של הכלים הם חופשיים/קוד־פתוח. יש לא מעט תוכנה ללינוקס, אם כי הדברים הטובים ביותר רצים על חלונות. רוב הדרייברים של המצלמות דווקא סגורים. אבל לרוב יש גרסאות לינוקס, Raspberry PI ועוד.

עכשיו, בצילום אסטרונומי יש נדבך חשוב שמעניין אותו במיוחד: Electronically Assisted Astronomy או EAA בקיצור. פירושו ביצוע כל הפעולות הנדרשות לצילום (כולל עיבוד, איסוף תמונות והערמה) בזמן אמת, כאשר עם כל תמונה חדשה של האובייקט, אתה מקבל את התמונה הסופית המשופרת יותר ויותר. המטרה של EAA בניגוד לצילום, לא להגיע לתמונה הטובה ביותר אפשרית, אלא להגיע לתמונה שמספיק טובה כדי לראות את האובייקט ולהנות ממנו.

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

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

אבל לרובינו יש כבר מחשב די חזק ונייד: טלפון או טאבלט! לו רק יכולתי לחבר את המצלמה ישירות לאליהם...

אז הרמתי את דגל

בניתי פתרון ל־EAA עבור לינוקס ואנדרואיד ושמו OpenLiveStacker. והוא בנוי בצורה הבאה:

  • הקוד כתוב ב־C++‎ עם שימוש ב־OpenCV לצורך עיבוד תמונה
  • הממשק בנוי כ־web interface שמדבר ב־REST עם השרת - מה שמאפשר בניית ממשק בלינוקס ואנדרואיד באותה צורה וגם מקל על גישה מרחוק במקרה והתוכנה רצה על pi. כמובן שהשרת מבוסס CppCMS. מה שמאפשר חיבור קל ונוח בין הקוד שדורש ביצועים הגובהים לממשק משתמש.
  • הדרייברים נטענים דינאמית:
    • אחד עבור מצלמה גנרית עם פרוטוקול UVC על בסיס libusb/libuvc- שתומך במצלמות רשת או במצלמות כמו SVBony sv105 - אבל הוא מוגבל לצורכים אסטרונומיים
    • דרייבר של ASI ZWO - החברה המובילה בתחום, שעובד מול SDK שלהם. לצערי הדרייבר עצמו הוא קוד סגור, אבל יש להם גרסה לאנדרואיד.
    • דרייבר גנרי שיודע לקרוא קבצים מהספרייה איך שהם מגיעים - מה שמאפשר חיבור לכל מצלמה אחרת דרך כלים קיימים כמו indi/ekos.
  • לצורך תמיכה באנדרואיד יש אפליקציה קטנה שעוטפת את השרת ומנהלת גישה ל־USB (כי באנדרואיד הכל צריך להיות מסובך)
  • לצורך הקלה על התמצאות יש חיבור לתוכנה פופולרית מאוד בתחום אסטרונומיה: ASTAP שיש לה גם גרסה (קובץ ריצה) לאנדרואיד. הדבר המעניין בתוכנה הזו שהיא כתובה בפסקל! לא חשבתי שאתקל בדבר כזה בימינו.

מה למדתי?

  • בניית אפליקציות אנדרואיד זה די סיוט וזה לא בגלל השפה אלא בגלל שצריך ללמוד פחות או יותר הכל מ־0. מזל שרוב הקוד ניתן לכתוב ב־C++‎.
  • כמעט כל דבר באנדרואיד עובד "קצת שונה". למשל: אין לך ‎/tmp, להריץ exe חיצוני זה סיפור שעלה לי בלילה לבן, להביא קבצים עם אפליקציה זה גם לא משהו טריוויאלי. בקיצור. זה לינוקס, אבל לא בדיוק.
  • אני שונא לעבוד עם קוד סגור. אומנם ASI ZWO משחררים דרייברים לאנדרואיד, אבל הם גם הכניסו באג מעצבן שגורם ל־RTTI לא לעבוד! למעשה כל תכנת החיבור ל־SDK שלהם כתבתי ב־C+-‎ בגלל אי זמינות של RTTI. וזה לא היה משהו מסובך אם הייתי יכול לקמפל את הדרייבר מחדש הבעיה הייתה פשוט נעלמת.

שורה תחתונה

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

התקדמות חשובה בתמיכה ב־OpenCL ב־pytorch.

ב־יום חמישי, 3 בנובמבר 2022, מאת ארתיום; פורסם תחת: תכנה חופשית, פיתוח, תכנה ומחשבים, C++‎‏, בינה מלאכותית; ‏0 תגובות

רקע

היום pytorch היא אחת התשתיות המובילות בעולם למידה עמוקה. יש לה יתרונות רבות, אבל מבחינת המפתח זה קוד איכותי ותיעוד טוב. הקוד כתוב בצורה מאוד מודרנית עם שימוש נכון ביכולות C++‎ מה שמאוד מקל על הפיתוח. אני עובד בתקופה האחרונה על פיתוח מנוע עבור pytorch מבוסס OpenCL כחלופה ל־cuda.

כבר כתבתי בעבר על חשיבות התמיכה ב־OpenCL.

אבל בכל זאת אזכיר כמה נקודות מבחינת קהילת תוכנה חופשית וקוד פתוח:

  1. אנחנו זקוקים בתמיכה חוצת פלטפורמה בכרטיסי מסך מיצרנים שונים כמו AMD, Intel וכמובן nVidia.
  2. אנחנו זקוקים למימוש האלגוריתמים המרכזיים כקוד פתוח הזמין לכל (ולא כקופסה סגורה ש־nVidia נותנת)
  3. אנחנו רוצים לעבוד עם סטנדרטים פתוחים וזמינים כמו OpenCL ולא מימושים ספציפיים של יצרן (כמו cuda).

הפרוייקט ב־github‏

אז מה חדש? קלות אינטגרציה!

עם שחרור גרסה 1.13 של pytorch חל שיפור משמעותי ב־out-of-tree-backend. עכשיו הוספת מנוע אימון מבוסס OpenCL היא פשוטה מאוד ולמעשה שאלה של מספר דקות, אפילו בוונידוס העניין יחסית פשוט. המשמעות שאפשר להשתמש במנוע OpenCL בקלות רבה הן בלינוקס והן בווינדוס.

מה עם הביצועים? אם משווים מול גרסת cuda/cudnn על אותו ה־gpu מדובר בין 50 ל־70 אחוז ביצועי cuda באימון ובין כ־60 ל־80 באבלואציה (תלוי ברשת כמובן).

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

המנוע עצמו מבוסס על ספריית dlprimitives‏ שאני מפתח במקביל והיא חלופה ל־cuDNN על בסיס OpenCL וגם מנוע חיזוי שעובד עם מודלים בפורמט ONNX - שזה נושא גדול בפני עצמו.

מה המשמעות של זה?

  • משתמשי AMD יכולים לאמן רשתות. הם לא מוגבלים למספר מצומצם של דגמים ש־rocm תומך בהם או לשימוש בלינוקס בלבד. התמיכה היא גורפת מ־APUים ישנים כמו Stoney Ridge ועד ל־RDNA 2 וגם זה עובד על "חלונות" למי שמעוניין.

    זו הייתה משימה כמעט ובלי אפשרית עד היום. עכשיו זה במרחק מספר פקודות

  • תשתית אימון היא קוד פתוח לגמרי גם אם עובדים עם nVidia (טוב חוץ מהדרייבר שלהם)

  • כל מה שצריך זה דרייברי של OpenCL. לא צריך את כל המפלצת של cuda (מי שיצא לו להתקין לשדרג לגלות בעיות תאימות יבין אותי מידי)

מחפש עזרה...

מישהו יודע איך אפשר לבנות ולפרסם whl לפלטפורמות שונות? רצוי איזה שירות ענן שיעשה זאת? כדי שזה יהיה ממש במרחק של pip install :-)

CppCMS עובר מ-LGPLv3 ל-MIT

ב־יום שלישי, 16 בינואר 2018, מאת ארתיום; פורסם תחת: תכנה חופשית, לינוקס, פיתוח, תכנה ומחשבים, CppCMS, C++‎‏; ‏0 תגובות

היום עדכנתי רישיון של CppCMS ל-MIT. הגרסה הקרובה 1.2 תשוחרר עם רישיון מעודכן

ההחלטה נובעת ממספר סיבות:

  1. רצון להגדיל נתח השוק של CppCMS ולהקל על כניסה של משתמשים חדשים
  2. להביא יותר מפתחים לפרויקט

אחרי תקופה ארוכה שוחררה בטא של CppCMS 1.1.0

ב־יום רביעי, 12 ביולי 2017, מאת ארתיום; פורסם תחת: תכנה חופשית, פיתוח, CppCMS, C++‎‏; ‏0 תגובות

אחרי תקופה ארוכה של המתנה שוחררה גרסת בטא 1.1.0 של CppCMS. גרסה זו מכילה המון שיפורים ושיוניים. ביניהם:

  • תכנון מחדש של application pool לתיקון מספר בעיות מובנות שהיו קיימות בו עד כה
  • API חדש של פעולות non-blocking לשיפור משמעותי בביצועי אפליקציות אסינכרוניות
  • סיכון ועיבוד בזמן העלאה של התוכן (למשל עיבוד או בדיקה של קבצים תוך כדי העלאה)
  • תמיכה משופרת ב-RESTful API
  • מערכת לניהול plugin ושיפורים מערכת תבניות (templates) בהם.
  • אפשרות ניהול session ללא עוגיות (למקרה והמשתמש ממש צריך)
  • שילוב ניהול ה-session מול טכנולוגיות אחרות כולל מימוש עבור PHP, Java Servlet, ASP.Net ו-Python Django
  • שיפורי ביצועים רבים
  • ועוד...

התכנון הוא לבצע בדיקת בטא מהירה, לשחרר 1.2 כגרסה יציבה (גם ככה חלק ניכר מהמשתמשים כבר עובד בענף הפיתוח ב-git).

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

  • ל-1.4 תמיכה מלאה ב-HTTP/1.1, ב-HTTPS ומימוש של websockets
  • ל-2.0 להעביר CppCMS ל-C++11 תוך ניקוי חלק מה-API שילקח מספריה סטנדרטית כמו std::shared_ptr

אתם מוזמנים להתנסות בגרסת בטא האחרונה!

שילוב בין טכנולוגיות Web שונות ו-CppCMS

ב־יום שני, 16 בנובמבר 2015, מאת ארתיום; פורסם תחת: תכנה חופשית, פיתוח, CppCMS, C++‎‏, Java; ‏8 תגובות

כשיש לך מערכת ווב גדולה ומפותחת ואתה צריך להעביר חלקים קריטיים ממנה לטכנולוגיה מהירה יותר (קרי CppCMS) אתה נתקל קודם כל בבעיה הבסיסית - איך לשתף מידע.

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

לכן, יצרתי שכבת תיאמות שמאפשרת לגשת ל-Session של CppCMS מכל שפת תכנות אחרת.

בשלב ראשון עדכנתי את המחלקות הקשירות לניהול ה-Session של CppCMS שיוכלו לפעול בצורה בלתי תלויה מהמערכת. יצרתי API נקי מבוסס C בלבד כדי שלא יהיו בעיות כמו חריגות (exceptions) האופייניות ל-++C וגם כדי שאפשר היה לטעון את הפונקיות ישירות בעזרת dlopen.

אחר כך יצרתי מספר מודולים עבור שפות שונות:

  • PHP עם שימוש ב-Swig
  • Java/Servlet עם שימוש ב-JNA
  • Python עם שימוש ב-ctypes והתממשקות עם Django (אבל לא מוגבל ל-Django)
  • Asp.Net עם שימוש ב-PInvoke

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

חייב להגיד לכל טכנולויה היו בעיות משלה... למשל ב-Python היו התנהגויות מוזרות כשניסיתי לבנות מתודות באופן דינאמי, ב-Java/JNA הכל עבר חלק להבפליא. PInvoke שיגע אותי עם חוסר רצון שלו להמיר UTF-8 ל-string ובחזרה (אגב Mono כן עושה זאת בצורה שקופה אבל לא Net. של Windows מתעקש להשתמש בקידוד ANSI). יצירת מודולים עם Swig עבדה לא רע בכלל, אבל נדרשת עוד מעטפת כדי להתאים את הכל בסופו של דבר לשפה עצמה והתנהגותה.

ואיך זה נראה

PHP:

// pool initialization
$pool=CppCMS_SessionPool::from_config('cppcms-config.js');
// per request session access
$session=$pool->session();
$session->load();
$x=0;
if($session->is_set('x')) {
        $x=$session['x'];
}

$x=intval($x)+1;
$session['x']=$x;
$session->save();
...

Java/Servlet:

static SessionPool pool;

public void init() throws ServletException
{
    pool = SessionPool.openFromConfig("/path/to/cppcms-config.js");
}

public void doGet(HttpServletRequest request,
                  HttpServletResponse response) 
                    throws ServletException, IOException
{
    Session session = pool.getSession();
    session.load(request);
    String x="0";
    if(session.isSet("x"))
        x=session.get("x");
    x=Integer.toString(Integer.parseInt(x)+1);
    session.set("x",x);
    session.save(response);
    session.close();
    ...
}

Python/Django:

# Create global pool
pool=cppcms.SessionPool('/path/to/cppcms-config.js')

# Actual view
def home(request):
    s=pool.session()
    s.load(django_request=request)
    v='0'
    if 'x' in s:
            v= s['x']
    s['x']=str(int(v)+1)
    response = HttpResponse()
    s.save(django_response=response)
    ...

C#/ASP.Net:

static SessionPool pool;
static Example() {
    pool = SessionPool.FromConfig("cppcms-config.js");
}
protected void Page_Load(object sender,EventArgs e)
{
    using(Session s = pool.Session()) {
        s.Load(Request);
        string v="0";
        if(s.IsSet("x"))
            v=s["x"];
        v = (int.Parse(v) + 1).ToString();
        s["x"]=v;
        s.Save(Response);
    }
    ...
}

אפשר לראות את הקוד והדוגמאות המלאות כאן

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

העמוד הבא

דפים

נושאים