σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
uantCraft Academyخرائط الطريقالمسارات
Ctrl K
AO
+1.2k متعلّم
تسجيل الدخولانضم ↗
خرائط الطريقالمسارات
AO
+1.2k متعلّم
تسجيل الدخول
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
uantCraft Academyخرائط الطريقالمسارات
Ctrl K
AO
+1.2k متعلّم
تسجيل الدخولانضم ↗
خرائط الطريقالمسارات
AO
+1.2k متعلّم
تسجيل الدخول
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
مسار Lock-free›الوحدة 4 · الاختبار وسلامة الذاكرة›الموضوع 4.2·~1 س 10 دخبير

مؤشرات الخطر واسترجاع العصور

الموضع في المسارالوحدة 4 من 4 · الموضوع 2 من 3
4.2 مؤشرات الخطر واسترجاع العصور
—درجة المختبر— / 100إجمالي XP—التتابع—

3 دقيقة قراءة3 أمثلة برمجية

  1. 01التحرير الفوري: السحب غير الآمن
  2. 02مؤشرات الخطر: أعلن ثم تحقق
  3. 03العصور: أعلن متى دخلت
  4. 04ما ستبنيه

المكدس بلا أقفال لا يحجب أبدًا لكنه لا يستطيع ببساطة تحرير عقدة أخرجها: ربما قرأ خيط آخر الرأس قبل لحظة وهو على وشك قراءة next لتلك العقدة. الذاكرة المحرَّرة قد يُعاد استعمالها أو تُلغى فتكون تلك القراءة استعمالًا بعد التحرير. هناك علاجان كلاسيكيان. مؤشرات الخطر تتيح للخيط أن يعلن العقدة التي يستعملها. والعصور تتيح له أن يعلن متى دخل. وفي كليهما لا تُحرَّر العقدة المفصولة إلا حين لا يستطيع أحد إمساكها.

01

التحرير الفوري: السحب غير الآمن

النموذج هو مكدس موضوع ABA. يقرأ الخيط الرأس ثم العقدة ثم يبدّل الرأس بعملية compare-and-swap واحدة. يحرّر السحب غير الآمن العقدة في الدور نفسه الذي ينجح فيه التبديل. العقدة المحرَّرة لا يجوز لأحد لمسها وتسجّل read_node استعمالًا بعد التحرير كلما قرأ خيط واحدة منها. خيطان يسحب كل منهما مرة يعطيان 20 جدولًا فقط ويجد المستكشف السيئة فورًا: تلك التي قرأ فيها خيط الرأس وسحب الآخر العقدة وحرّرها ثم يقرؤها الأول.

main.pyPython
def pop_unsafe(shared, tid):    while True:        yield        idx = shared["head"]        if idx == -1:            return None        yield        nxt, value = read_node(shared, idx)        yield        if compare_and_swap(shared, "head", idx, nxt):            shared["popped"] = shared["popped"] + (value,)            free_node(shared, idx)            return valuedef two_pops(shared):    return [pop_unsafe(shared, 0), pop_unsafe(shared, 1)]outcomes = explore_all(two_pops, make_heap([9369, 9305]))hits = sum(n for key, n in outcomes.items() if dict(key)["uaf"])print(sum(outcomes.values()), "schedules,", hits, "of them read a freed node")
20 schedules, 6 of them read a freed node
02

مؤشرات الخطر: أعلن ثم تحقق

يحوّل مؤشر الخطر التحرير إلى حوار. قبل قراءة عقدة يكتب الخيط رقمها في خانته. وهذا وحده لا يكفي لأن العقدة قد تكون سُحبت وحُرّرت بين قراءة الرأس وكتابة الخانة فيقوم الخيط بـالتحقق: يقرأ الرأس مرة أخرى ويبدأ من جديد إن تحرك. وبعد سحب ناجح لا يحرّر الخيط العقدة بل يضعها في قائمته الخاصة بالمتقاعدة ويمسح: يقرأ خانة كل خيط مرة واحدة ويحرّر فقط العقد المتقاعدة التي لا تسميها خانة. وتنتظر العقد المتبقية مسحًا لاحقًا.

main.pyPython
def pop_hazard(shared, tid):    while True:        yield        idx = shared["head"]        if idx == -1:            shared["hp%d" % tid] = -1            return None        yield        shared["hp%d" % tid] = idx        yield        if shared["head"] != idx:            continue        yield        nxt, value = read_node(shared, idx)        yield        if compare_and_swap(shared, "head", idx, nxt):            shared["popped"] = shared["popped"] + (value,)            shared["hp%d" % tid] = -1            shared["retired%d" % tid] = shared["retired%d" % tid] + (idx,)            break    yield    hazards = tuple(shared["hp%d" % t] for t in range(shared["threads"]))    yield    keep = []    for node in shared["retired%d" % tid]:        if node in hazards:            keep.append(node)        else:            free_node(shared, node)    shared["retired%d" % tid] = tuple(keep)    return valuedef two_pops(shared):    return [pop_hazard(shared, 0), pop_hazard(shared, 1)]outcomes = explore_all(two_pops, make_heap([9369, 9305]))hits = sum(n for key, n in outcomes.items() if dict(key)["uaf"])waiting = max(sum(len(dict(key)["retired%d" % t]) for t in (0, 1)) for key in outcomes)print(sum(outcomes.values()), "schedules,", hits, "read a freed node, up to", waiting, "node waiting at the end")
12122 schedules, 0 read a freed node, up to 1 node waiting at the end
تعريفمؤشر الخطر

إعلان لكل خيط عن العقدة الوحيدة التي تُقرأ، يُكتب قبل القراءة ويُتحقَّق منه بعدها. لا تُحرَّر العقدة المتقاعدة إلا إذا لم يسمّها أي إعلان.

03

العصور: أعلن متى دخلت

يعلن استرجاع العصور أقل بكثير. هناك عدّاد عصر عام واحد. يكتب الخيط العصر الحالي في خانته عند دخول عملية ويكتب -1 عند الخروج ولا يعلن عقدًا بعينها أبدًا. العقدة المتقاعدة في العصر e لا يمسكها إلا خيط دخل في العصر e أو قبله فيأمن تحريرها حين يعلن كل خيط داخل عملية عصرًا أكبر من e. الثمن أن خيطًا يبقى طويلًا بالداخل يحبس كل العقد المتقاعدة منذ دخوله بينما يحبس مؤشر الخطر العقدة التي يسميها فقط.

main.pyPython
def pop_epoch(shared, tid):    yield    shared["ep%d" % tid] = shared["epoch"]    while True:        yield        idx = shared["head"]        if idx == -1:            shared["ep%d" % tid] = -1            return None        yield        nxt, value = read_node(shared, idx)        yield        if compare_and_swap(shared, "head", idx, nxt):            shared["popped"] = shared["popped"] + (value,)            shared["ep%d" % tid] = -1            shared["retired%d" % tid] = shared["retired%d" % tid] + ((idx, shared["epoch"]),)            shared["epoch"] = shared["epoch"] + 1            break    announced = []    for t in range(shared["threads"]):        yield        if shared["ep%d" % t] != -1:            announced.append(shared["ep%d" % t])    yield    keep = []    for node, epoch in shared["retired%d" % tid]:        if announced and epoch >= min(announced):            keep.append((node, epoch))        else:            free_node(shared, node)    shared["retired%d" % tid] = tuple(keep)    return valuedef two_pops(shared):    return [pop_epoch(shared, 0), pop_epoch(shared, 1)]outcomes = explore_all(two_pops, make_heap([9369, 9305]))hits = sum(n for key, n in outcomes.items() if dict(key)["uaf"])waiting = max(sum(len(dict(key)["retired%d" % t]) for t in (0, 1)) for key in outcomes)print(sum(outcomes.values()), "schedules,", hits, "read a freed node, up to", waiting, "node waiting at the end")
9012 schedules, 0 read a freed node, up to 1 node waiting at the end
التسرب ليس خطأً أما الخيط العالق فخطأ

يترك الأسلوبان عقدًا متقاعدة في الانتظار في نهاية بعض الجداول: يبلّغ المستكشف عنها بوصفها pending. يحرّرها مسح لاحق فلا يضيع شيء. الخطر الحقيقي للعصور خيط يتوقف داخل عملية: لا يعلن عصرًا أحدث أبدًا فلا تُحرَّر أي عقدة متقاعدة بعده وتنمو الذاكرة. ومؤشرات الخطر محصّنة لأن الخيط الواقف يحبس عقدة واحدة فقط.

ما تقوله البيانات الحقيقيةخيطان يسحب كل منهما مرة من مكدس أول إغلاقين لـSPY (9369 و9305 سنتًا)
تحرير فوري206 جداول تقرأ عقدة محرَّرة
مؤشرات الخطر12,122لا جدول يقرأ عقدة محرَّرة
العصور9,012لا جدول يقرأ عقدة محرَّرة
عقد تُركت في الانتظار1كحد أقصى للأسلوبين الآمنين

السلامة تكلّف جداول لأن كل إعلان وتحقق ومسح خطوة إضافية يستطيع الخيط الآخر التسلل إليها: صار 20 إلى 12122 و9012. ولهذا بالضبط يفيد المستكشف هنا. فهو لا يحتاج أن يعرف لماذا الأسلوب صحيح بل يفحص كل جدول من تلك الجداول.

04

ما ستبنيه

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

  • الدالة · السؤالتعتمد على
  • make_heap(values, threads)ما المشترك؟حساب بسيط
  • pop_unsafe(shared, tid)اسحب وحرّر فورًاحساب بسيط
  • pop_hazard(shared, tid)أعلن وتحقق وأحِل للتقاعد وامسححساب بسيط
  • pop_epoch(shared, tid)ادخل وأحِل للتقاعد بالعصر واسترجعحساب بسيط
  • violations(final)أي الثوابت انكسرت؟حساب بسيط
  • verify(scheme, values, pops)هل الأسلوب آمن تحت كل الجداول؟explore_allviolations
  • study(bars)أي أسلوب ينجو في مكدس SPY؟verify

أهم الخلاصات

  • التحرير بروتوكول. فصل العقدة لا يجعل تحريرها آمنًا: قد يكون أحدهم على وشك قراءتها.
  • مؤشر الخطر يسمّي عقدة والعصر يسمّي زمنًا. تحتاج مؤشرات الخطر إلى تحقق بعد الإعلان؛ والعصور أرخص لكن خيطًا واقفًا يحبس كل شيء.
  • دع المستكشف يجد الثغرة. احذف التحقق فتقرأ جداول من الـ12122 ذاكرة محرَّرة.
تحقق سريع
قرأ الخيط A الرأس (العقدة 0) ولم يعلنها بعد. يسحب الخيط B العقدة 0 ويمسح. ماذا يجب على الخيط A فعله بعد إعلان العقدة 0؟
اختر إجابة.

الموضوع التالي: كان هذا مكدسًا ولعبة صغيرة. المشروع الختامي توزيع بيانات سوق بلا أقفال يشغّل المهارة كلها: تتدفق نقرات SPY من منتج واحد إلى عدة مستهلكين عبر بنية بلا أقفال ويثبت المستكشف ثوابتها تحت كل الجداول.

المختبر: ما الذي يُقيَّم

7 مهام · 100 نقطة
  • الحالة المشتركة5 نقطة
  • التحرير الفوري10 نقطة
  • مؤشرات الخطر20 نقطة
  • العصور20 نقطة
  • الثوابت10 نقطة
  • المدقق15 نقطة
  • الدراسة على جدول SPY20 نقطة
المستكشف · lab-lf-10
▾ lab-lf-10
▾ data
…
bash · داخل المتصفح
learner@quantcraft:~/lab-lf-10$
لم يتم تحميل Python بعدPythonLn 1, Col 1Spaces: 4UTF-8

هل تريد إعادة ضبط هذا الموضوع؟

سيعود كل ما في lab-lf-10 إلى الملفات الابتدائية وستُمسح الطرفية. ستفقد حلّك الحالي ولا يمكن التراجع عن ذلك.

سيُعاد ضبطه
  • main.py ← الشيفرة الابتدائية
  • سجل الطرفية ومخرجات الاختبارات
  • التغييرات غير المُرسلة
سيُحتفظ به
  • أفضل درجة في المختبر
  • نقاط XP والتتابع
  • تقدّم المحاضرة والملاحظات