Julia: مصفوفة الضرب API

تم إنشاؤها على ٢٨ سبتمبر ٢٠١٧  ·  208تعليقات  ·  مصدر: JuliaLang/julia

حاليًا ، يوجد السطر التالي في كود matmult المتناثر:

https://github.com/JuliaLang/julia/blob/056b374919e11977d5a8d57b446ad1c72f3e6b1d/base/sparse/linalg.jl#L94 -L95

أفترض أن هذا يعني أننا نريد الحصول على طرق A_mul_B*!(α,A,B,β,C) = αAB + βC الأكثر عمومية والتي تحل محل C (API BLAS gemm ) للمصفوفات الكثيفة. لا يزال هذا هو الحال؟ (يبدو أيضًا أنه من الممكن الاحتفاظ بكل من واجهات برمجة التطبيقات ، أي الاحتفاظ بالطرق A_mul_B*!(C,A,B) ، والتي يمكن تعريفها ببساطة على أنها A_mul_B*!(C,A,B) = A_mul_B*!(1,A,B,0,C) .)

أرغب شخصيًا في تحديد واجهة برمجة تطبيقات gemm لجميع أنواع المصفوفات (تم التعبير عن هذا في مكان آخر ). يبدو تنفيذ هذه الطرق على المصفوفات الكثيفة أمرًا بسيطًا إلى حد ما ، نظرًا لأنها ستستدعي مباشرةً gemm et al. تم تنفيذ الحالة المتفرقة بالفعل. سيكون التعديل الحقيقي الوحيد هو julia generic matmult ، والذي لا يقبل α و β .

سيؤدي هذا إلى رمز عام يعمل مع أي نوع من المصفوفات / الأرقام. لدي حاليًا تطبيق بسيط لـ expm (بعد إجراء التعديل على _generic_matmatmult! ) والذي يعمل مع bigfloats والمصفوفات المتفرقة.

linear algebra

التعليق الأكثر فائدة

أقترح جولة تصويت واحدة للموافقة مع مهلة 10 أيام من الآن. التصويت بالموافقة يعني: يصوت الجميع لجميع الخيارات التي يرونها مفضلة على مواصلة المناقشة. يجب على الأشخاص الذين يفضلون الحصول على أقل الأسماء المفضلة لديهم الآن بدلاً من المناقشة المستمرة التصويت لجميع الثلاثة. إذا لم يحظ أي خيار بموافقة واسعة النطاق ، أو إذا فشل مخطط التصويت نفسه في تلبية موافقة واسعة النطاق ، فيجب علينا مواصلة المناقشة. في حالة شبه العلاقات بين الخيارات المعتمدة ، فإن tkf يقرر (امتياز مؤلف العلاقات العامة).

+1: أوافق على نظام التصويت هذا وقد أدليت بصوتي.
-1: أنا لا أتفق مع نظام التصويت هذا. إذا حدد الكثير من الأشخاص أو المهمين جدًا هذا الخيار ، فسيكون التصويت موضع نقاش.

القلب: يُفضل mul! للمناقشة المستمرة.
الصاروخ: يُفضل muladd! للمناقشة المستمرة.
الصيحة: يُفضل addmul! للمناقشة المستمرة.

أقترح مبدئيًا أن 75٪ موافقة و 5 يجب أن يكتمل النصاب القانوني (أي 75٪ من الأشخاص الذين صوتوا على الإطلاق ، بما في ذلك عدم الموافقة على إجراء التصويت بأكمله ، ووافق 5 أشخاص على الأقل على الخيار الفائز ؛ إذا كانت المشاركة منخفضة ، ثم 5/6 أو 6/8 يكتمل النصاب ولكن بالإجماع 4/4 يمكن اعتباره فشلًا).

ال 208 كومينتر

المرجع. # 9930 ، # 20053 ، # 23552. الأفضل!

شكرا على المراجع. أفترض أن هذه المشكلة لها علاقة بإضافة أساليب gemm -style بدلاً من تجديد واجهة برمجة التطبيقات ، ولكن يمكن إغلاقها إذا كنا نعتقد أنها لا تزال مشابهة جدًا لـ # 9930.

كنقطة بداية ، هل سيكون هناك دعم لامتلاك _generic_matmatmul! gemm API α=1 و β=0 . يمكنني تقديم العلاقات العامة. من المحتمل أن أذهب بشكل مشابه إلى هذا الإصدار (في هذا الإصدار ، قمت بقص كل العناصر المقلوبة لأنني لم أكن بحاجة إليها ، لن أفعل ذلك هنا).

نعم. من شأنه أن يكون بداية جيدة. لكننا بحاجة إلى النظر في ترتيب الحجج. في الأصل ، اعتقدت أنه من الطبيعي اتباع ترتيب BLAS ولكننا متسقين إلى حد ما بشأن وجود وسيطات الإخراج أولاً ، وهو ما ينطبق أيضًا على الوسيطات الثلاثة الحالية A_mul_B! . علاوة على ذلك ، وكما أشرت بالفعل ، فإن الإصدار المكون من ثلاث وسيطات سيتوافق مع الإصدار المكون من خمس وسيطات مع α=1 و β=0 وسيطات القيمة الافتراضية هي الأخيرة. بالطبع ، لا يتعين علينا بالضرورة استخدام صيغة القيمة الافتراضية لهذا ، ولكن سيكون من المنطقي استخدامها هنا.

لماذا لا تقدم فقط وظيفة gemm ؟

نعم. من شأنه أن يكون بداية جيدة. لكننا بحاجة إلى النظر في ترتيب الحجج. في الأصل ، اعتقدت أنه من الطبيعي اتباع ترتيب BLAS لكننا متسقين إلى حد ما بشأن وجود وسيطات الإخراج أولاً وهو أيضًا الحال بالنسبة للوسيطات الثلاث الحالية A_mul_B! علاوة على ذلك ، وكما أشرت بالفعل ، سيتوافق الإصدار المكون من ثلاث وسيطات مع الإصدار المكون من خمس وسيطات مع α = 1 و β = 0 وتكون وسيطات القيمة الافتراضية هي الأخيرة. بالطبع ، لا يتعين علينا بالضرورة استخدام صيغة القيمة الافتراضية لهذا ، ولكن سيكون من المنطقي استخدامها هنا.

يبدو جيدا. يمكننا مواصلة النقاش حول ترتيب الوسيطة الفعلي وإعادة تسمية الطريقة في # 9930. هذا هو أكثر حول مجرد وجود النسخة خمسة حجة المتاحة، ولذا فإنني سوف تبقي الحالية Ax_mul_Bx!(α,A,B,β,C) اجهة.

لماذا لا تقدم فقط وظيفة الأحجار الكريمة العامة؟

هل تقترح إعادة تسمية _generic_matmatmul! إلى gemm! بالإضافة إلى التغييرات أعلاه؟

لكي أكون أكثر وضوحًا ، أعتقد أنه يجب أن ينتهي بنا الأمر إلى الحصول على طريقة واحدة mul(C,A,B,α=1,β=0) ، جنبًا إلى جنب مع أنواع التحويل الكسول / المساعدة للإرسال ، ولكن هذا سيكون علاقات عامة أخرى.

لماذا لا تقدم فقط وظيفة الأحجار الكريمة العامة؟

أعتقد أن gemm تسمية خاطئة في جوليا. في BLAS ، يشير الجزء ge إلى أن المصفوفات عامة ، أي ليس لها بنية خاصة ، وأن أول m يتضاعف والقائمة m مصفوفة . في جوليا ، يتم ترميز الجزء ge (عام) في التوقيع كما هو m (مصفوفة) الأخيرة لذا أعتقد أنه يجب علينا فقط تسميتها mul! .

هو التدوين mul!(α, A, B, β, C) من SparseArrays.jl

https://github.com/JuliaLang/julia/blob/160a46704fd1b349b5425f104a4ac8b323ea85af/stdlib/SparseArrays/src/linalg.jl#L32

"وضع اللمسات الأخيرة" كالصيغة الرسمية؟ وسيكون هذا بالإضافة إلى mul!(C, A, B) و lmul!(A, B) و rmul!(A,B) ؟

أنا لست معجبًا كبيرًا بامتلاك A و B و C في طلبات مختلفة.

هل التدوين mul!(α, A, B, β, C) من SparseArrays.jl "انتهى" باعتباره الصيغة الرسمية؟

سأقول لا. في الأصل ، أعجبتني فكرة اتباع BLAS (وكان الترتيب يتطابق أيضًا مع كيفية كتابة هذا عادةً رياضيًا) ولكني الآن أعتقد أنه من المنطقي إضافة حجج القياس كوسيطتين اختياريتين رابعة وخامسة.

لذا فقط للتوضيح ، تريد حججًا اختيارية بالمعنى

function mul!(C, A, B, α=1, β=0)
 ...
end

سيكون الخيار الآخر عبارة عن وسائط اختيارية للكلمات الرئيسية

function mul!(C, A, B; α=1, β=0)
...
end

لكني لست متأكدًا من أن الناس سعداء جدًا باستخدام unicode.

أنا سعيد جدًا باستخدام unicode ولكن صحيح أننا نحاول دائمًا أن يكون لدينا خيار ascii وسيكون ذلك ممكنًا هنا. الأسماء α و β ليست أيضًا بديهية للغاية إلا إذا كنت تعرف BLAS لذلك أعتقد أن استخدام الحجج الموضعية هو الحل الأفضل هنا.

في رأيي ، فإن التسمية الأكثر منطقية هي السماح لـ muladd!(A, B, C, α=1, β=1) بالتعيين إلى إجراءات BLAS المختلفة التي تقوم بالضرب والإضافة . ( gemm كما هو مذكور أعلاه ، ولكن أيضًا على سبيل المثال axpy عندما يكون A عددًا.)

يمكن أن تحتوي الوظيفة mul! بعد ذلك على واجهة مثل mul!(Y, A, B, ...) تأخذ عددًا عشوائيًا من الوسائط (تمامًا مثل * ) طالما يمكن تخزين جميع النتائج الوسيطة في Y. ( يمكن أن يحدد kwarg الاختياري ترتيب الضرب ، مع افتراض معقول)

mul!(Y, A::AbstractVecOrMat, B:AbstractVecOrMat, α::Number) سيكون له التطبيق الافتراضي muladd!(A, B, Y, α=α, β=0) ، كما هو الحال مع التباديل الأخرى لمصفوفتين / متجهين وعدد.

تصويت آخر لتحديد mul!(C, A, B, α, β) للمصفوفات الكثيفة. سيسمح هذا بكتابة رمز عام لمصفوفات كثيفة ومتفرقة. أردت تحديد مثل هذه الوظيفة في حزمة المربعات الصغرى غير الخطية ولكن أعتقد أن هذا نوع قرصنة.

كما أنني قد يميل لكتابة mul!(C, A, B, α, β) طرق ل MixedModels حزمة والدخول في شيء من نوع القرصنة، لكنه سيكون أفضل بكثير إذا كانت هذه الأساليب في LinearAlgebra صفقة. سيكون وجود طرق لـ muladd! عام لهذه العملية مناسبًا لي أيضًا.

أنا أؤيده ، على الرغم من أنني أعتقد أنه من المحتمل أن يكون له اسم مختلف عن مجرد mul! . muladd! معقولًا ، لكنني بالتأكيد منفتح على الاقتراحات.

ربما mulinc! لمضاعفة الزيادة؟

ربما يمكننا الحصول على شيء مثل addmul!(C, A, B, α=1, β=1) ؟

أليس هذا شكل من أشكال muladd! ؟ أم أن الفكرة من تسميتها addmul! أنها تغير وسيطة الجمع بدلاً من وسيطة الضرب؟ هل يمكن للمرء أن يغير حجة الضرب؟

لاحظ أننا نقوم بتغيير العناصر غير الأولى في بعض الحالات ، على سبيل المثال lmul! و ldiv! ، لذلك يمكننا القيام بها بترتيب "muladd" المعتاد (مثل muladd!(A,B,C) ). السؤال هو ما هو الطلب الذي يجب أن يذهب إليه α و β ؟ سيكون أحد الخيارات لجعل الحجج الكلمات الرئيسية؟

ألن يكون لطيفًا إذا تركت خيارًا للمنفذين للإرسال إلى أنواع العددية α و؟ من السهل إضافة السكريات للمستخدمين النهائيين.

اعتقدت أننا استقرنا بالفعل على mul!(C, A, B, α, β) مع القيم الافتراضية لـ α ، β . نحن نستخدم هذا الإصدار في https://github.com/JuliaLang/julia/blob/b8ca1a499ff4044b9cb1ba3881d8c6fbb1f3c03b/stdlib/SparseArrays/src/linalg.jl#L32 -L50. أعتقد أن بعض الحزم تستخدم هذا النموذج أيضًا ولكني لا أتذكر أيها فوق رأسي.

شكر! سيكون من الرائع لو تم توثيق ذلك.

اعتقدت أننا استقرنا بالفعل على mul!(C, A, B, α, β) مع القيم الافتراضية لـ α ، β .

تستخدمه SparseArrays ، لكنني لا أتذكر أنه تمت مناقشتها في أي مكان.

من بعض النواحي ، يكون الاسم muladd! طبيعيًا لأنه عملية ضرب متبوعة بإضافة. ومع ذلك ، فإن القيم الافتراضية لـ α و ، muladd!(C, A, B, α=1, β=0) (لاحظ أن القيمة الافتراضية لـ β هي صفر وليست واحدة) ، أعدها مرة أخرى إلى mul!(C, A, B) .

يبدو أنها حالة من التحذلق مقابل الاتساق سواء كان استدعاء هذا mul! أو muladd! وأعتقد أن حالة الطريقة الحالية في SparseArrays ستجادل بـ mul! . أجد نفسي في حالة غريبة تتمثل في الدفاع عن الاتساق على الرغم من اقتباس أوسكار وايلد المفضل لدي ، "الاتساق هو الملاذ الأخير للخيال."

من بعض النواحي ، يكون الاسم muladd! طبيعيًا لأنه عملية ضرب متبوعة بإضافة. ومع ذلك ، فإن القيم الافتراضية لـ α و ، muladd!(C, A, B, α=1, β=0) (لاحظ أن القيمة الافتراضية لـ β هي صفر وليست واحدة) ، أعدها مرة أخرى إلى mul!(C, A, B) .

هناك استثناء مثير للاهتمام لهذا عندما يحتوي C على Infs أو NaN: نظريًا ، إذا كان β==0 ، يجب أن تظل النتيجة NaNs. لا يحدث هذا عمليًا لأن BLAS وكود المصفوفة المتناثرة الخاص بنا β==0 ثم استبدله بالأصفار.

يمكنك اعتبار أن وجود قيم افتراضية α=true, β=false نظرًا لأن true و false هما "قوي" 1 و 0 على التوالي ، بمعنى أن true*x هو دائمًا x و false*x دائمًا zero(x) .

يجب أن يمتلك lmul! هذا السلوك الاستثنائي أيضًا: https://github.com/JuliaLang/julia/issues/28972

true و false "قوي" 1 و 0 على التوالي ، بمعنى أن true*x دائمًا x و false*x دائمًا zero(x) .

لم أكن أعرف ذلك !:

julia> false*NaN
0.0

FWIW ، أنا سعيد جدًا بإمكانية قراءة صيغة LazyArrays.jl لهذه العملية:

y .= α .* Mul(A,x) .+ β .* y

خلف الكواليس ، تنخفض إلى mul!(y, A, x, α, β) ، للمصفوفات المتوافقة مع BLAS (النطاقات والمخططة).

لم أكن أعرف ذلك!

إنه جزء مما يجعل im = Complex(false, true) يعمل.

تستخدمه SparseArrays ، لكنني لا أتذكر أنه تمت مناقشتها في أي مكان.

تمت مناقشته أعلاه في https://github.com/JuliaLang/julia/issues/23919#issuecomment -365463941 وتم تنفيذه في https://github.com/JuliaLang/julia/pull/26117 دون أي اعتراضات. ليس لدينا إصدارات α,β في الحالة الكثيفة ، لذا فإن المكان الوحيد في هذا الريبو حيث يكون للقرار تأثير فوري سيكون SparseArrays .

ماذا عن LinearAlgebra.BLAS.gemm! ؟ ألا يجب أن يتم تغليفه كـ 5-ary mul! أيضًا؟

يجب أن تفعل ذلك ولكن لا أحد قد فعل ذلك بعد. هناك العديد من الطرق في matmul.jl .

نوقش أعلاه في # 23919 (تعليق) ونفذ في # 26117 دون أي اعتراضات.

حسنًا ، اعتبر هذا اعتراضي. أفضل اسم مختلف.

لماذا سيكون اسمًا مختلفًا؟ في كل من الحالة الكثيفة والمتفرقة ، تقوم الخوارزمية الأساسية بالضرب والجمع.

إذا أعطينا هذه الوظائف أسماء مختلفة ، فسيكون لدينا mul!(C,A,B) = dgemm(C,A,B,1,0) و muladd!(C,A,B,α, β) = dgemm(C,A,B,α, β) .

الميزة الوحيدة التي أراها هي إذا قمنا بالفعل بتقسيم الطرق وحفظنا مكالمة if β==0 في حالة C = A*B .

لمعلوماتك ، بدأت العمل عليه في # 29634 لإضافة الواجهة إلى matmul.jl . آمل أن أنهيها بحلول الوقت الذي يتم فيه تحديد الاسم والتوقيع :)

تتمثل ميزة muladd! أنه يمكننا الحصول على muladd!(A, B, C) (أو muladd!(C, A, B) ؟) مع α = β = true الافتراضي (كما هو مذكور في الاقتراح الأصلي https: //github.com/JuliaLang/julia/issues/23919#issuecomment-402953987). الطريقة muladd!(A, B, C) تشبه muladd لـ Number s لذلك أعتقد أنه اسم طبيعي أكثر خاصة إذا كنت تعرف muladd .

andreasnoack يبدو أن تدور حول توقيع الأسلوب وتفضيل الحجج الموضعية على وسيطات الكلمات الرئيسية ، وليس اسم الطريقة. هل لديك اعتراض على الاسم muladd! ؟ (قد يكون وجود 5-ary mul! في SparseArrays واحدًا ، لكن تحديد الغلاف المتوافق مع الإصدارات السابقة ليس بالأمر الصعب.)

يبدو أن وجود كل من mul! و muladd! زائد عن الحاجة عندما يكون الأول هو الأخير فقط مع القيم الافتراضية لـ α و β . علاوة على ذلك ، تم اعتماد الجزء add بواسطة BLAS. إذا تمكنا من التوصل إلى تطبيق جبر خطي عام ذي مصداقية مقابل muladd! ، أود أن أسمع عنه ولكن بخلاف ذلك أفضل تجنب التكرار.

أيضًا ، أفضّل بشدة أن نبقي خاصية الصفر القوي وهي false منفصلة عن مناقشة mul! . يجب أن تكون أي قيمة صفرية لـ β في IMO قوية كما هو الحال في BLAS وكما هو الحال في الوسيطات الخمس الحالية mul! الطرق. أي يجب أن يكون هذا السلوك نتيجة mul! وليس نوع β . البديل سيكون صعب العمل معه. على سبيل المثال ، mul!(Matrix{Float64}, Matrix{Float64}, Matrix{Float64}, 1.0, 0.0) ~ لا يمكنه استخدام BLAS.

لا يمكننا تغيير ما يفعله BLAS ، ولكن _طلب_ سلوك صفري قوي للعوامات يعني أن كل تنفيذ سيحتاج إلى فرع للتحقق من الصفر.

إذا تمكنا من التوصل إلى تطبيق جبر خطي عام موثوق به مقابل muladd!

andreasnoack بهذا ، أفترض أنك تعني "تطبيق لـ _three -uments_ muladd! " وإلا فلن توافق على تضمين الخمس وسائط mul! ؟

لكن لا يزال بإمكاني الخروج بمثال يكون فيه muladd!(A, B, C) مفيدًا. على سبيل المثال ، إذا كنت ترغب في إنشاء شبكة "عالم صغير" ، فمن المفيد أن يكون لديك تجميع "كسول" لمصفوفة متفرقة ومصفوفة متفرقة. يمكنك بعد ذلك كتابة شيء مثل:

A :: SparseMatrixCSC
B :: BandedMatrix
x :: Vector  # input
y :: Vector  # output

# Compute `y .= (A .+ B) * x` efficiently:
fill!(y, 0)
muladd!(x, A, y)  # y .+= A * x
muladd!(x, B, y)  # y .+= B * x

لكنني لا أمانع في كتابة true s يدويًا حيث يمكنني ببساطة تغليفها لاستخدامي. إن وجود وظيفة من خمس وسيطات باعتبارها API موثقة مستقرة هو الهدف الأكثر أهمية هنا.

العودة إلى النقطة:

يبدو أن الحصول على كل من mul! و muladd! زائدا عن الحاجة عندما يكون الأول هو الأخير فقط مع القيم الافتراضية لـ α و β .

ولكن لدينا بعض * تنفيذه بدلالة mul! مع تهيئة "القيمة الافتراضية" لمصفوفة المخرجات بشكل مناسب. أعتقد أن هناك أمثلة "مختصرة" في Base والمكتبات القياسية؟ أعتقد أنه من المنطقي أن يكون لديك كلاً من mul! و muladd! على الرغم من أن mul! هو مجرد اختصار لـ muladd! .

أفضّل بشدة أن نبقي خاصية الصفر القوية البالغة false منفصلة عن مناقشة mul!

أوافق على أنه سيكون من البناء التركيز على مناقشة اسم النسخة المكونة من خمس وسيطات للإضافة المضاعفة أولاً ( mul! مقابل muladd! ).

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

يمكن كتابة مثالك كـ

mul!(y, A, x, 1, 1)
mul!(y, B, x, 1, 1)

لذلك ما زلت لا أرى الحاجة إلى muladd! . هل تعتقد أن هذه الحالة شائعة جدًا لدرجة أن كتابة 1, 1 مطول جدًا؟

لكن لدينا بعض * تنفيذه بدلالة mul! مع تهيئة "القيمة الافتراضية" لمصفوفة المخرجات بشكل مناسب. أعتقد أن هناك أمثلة "مختصرة" في Base والمكتبات القياسية؟

لا أفهم هذا. هل يمكنك محاولة التفصيل؟ ما هي الاختصارات التي تتحدث عنها هنا؟

لذلك ما زلت لا أرى الحاجة إلى muladd! . هل تعتقد أن هذه الحالة شائعة جدًا لدرجة أن كتابة 1, 1 مطول جدًا؟

أعتقد أن muladd! هو أيضًا أكثر وصفًا لما يفعله بالفعل (على الرغم من أنه ربما يجب أن يكون addmul! ).

ليس لدي مشكلة في الاسم muladd! . في المقام الأول ، لا أعتقد أنه يجب علينا القيام بوظائف لهذا ، وثانيًا لا أعتقد أن إهمال mul! لصالح muladd! / addmul! يستحق ذلك.

هل تعتقد أن هذه الحالة شائعة جدًا لدرجة أن كتابة 1 ، 1 مطولة جدًا؟

لا. أنا بخير تمامًا مع استدعاء وظيفة الحجة الخمسة طالما أنها واجهة برمجة تطبيقات عامة. لقد حاولت فقط أن أعطي مثالاً حيث أحتاج فقط إلى نسخة من ثلاث حجة (كما اعتقدت أن هذا كان طلبك).

ما هي الاختصارات التي تتحدث عنها هنا؟

https://github.com/JuliaLang/julia/blob/f068f21d6099632bd5543ad065d5de96943c9181/stdlib/LinearAlgebra/src/matmul.jl#L140 -L143

أعتقد أن * المحدد هنا يمكن اعتباره اختصارًا لـ mul! . إنها "فقط" mul! بقيمة افتراضية. فلماذا لا تدع mul! يكون muladd! / addmul! مع القيم الافتراضية؟

يوجد أيضًا rmul! و lmul! "اختصارات" مشابهة:

https://github.com/JuliaLang/julia/blob/f068f21d6099632bd5543ad065d5de96943c9181/stdlib/LinearAlgebra/src/triangular.jl#L478 -L479

إهلاك mul!

اعتقدت أن المناقشة كانت حول إضافة واجهة جديدة أم لا. إذا كنا بحاجة إلى إهمال mul! لإضافة واجهة برمجة تطبيقات جديدة ، فلا أعتقد أن الأمر يستحق ذلك.

الحجج الرئيسية التي يمكنني التفكير فيها هي:

  • من الناحية المفاهيمية ، فإن الصيغة المكونة من 5 حجج تفعل أكثر من مجرد "الضرب" ، وتنقل ذلك بشكل أوضح.
  • يمكنك بعد ذلك كتابة addmul!(C, A, B) بدلاً من mul!(C,A,B,1,1) أو mul!(C,A,B,true,true) .

أعتقد أن * المحدد هنا يمكن اعتباره اختصارًا لـ mul! . إنها "فقط" mul! بقيمة افتراضية. لذا ، لماذا لا تدع mul! أن تكون muladd! / addmul! مع القيم الافتراضية؟

لأن * هي الطريقة الافتراضية لضرب المصفوفات وكيف يفعلها معظم المستخدمين. بالمقارنة ، لن يكون muladd! قريبًا من استخدام * . علاوة على ذلك ، فهو عامل حالي بينما muladd! / addmul! سيكون وظيفة جديدة.

لا أعتقد أن rmul! و lmul! يتناسبان مع هذا النمط لأنها عمومًا ليست إصدارات قيمة افتراضية لطرق mul! خارج المكان.

يلخص سيمون الفوائد بشكل جيد في المنشور أعلاه. السؤال هو ما إذا كانت الفوائد كبيرة بما يكفي لتبرير وظيفة إضافية لإعادة التسمية (مما يعني إهمال mul! ). إنه المكان الذي نختلف فيه. لا أعتقد أن الأمر يستحق ذلك.

عندما تقول إن إعادة التسمية لا تستحق العناء ، هل أخذت في الاعتبار أن واجهة برمجة التطبيقات ليست عامة تمامًا؟ بهذا ، أعني أنه ليس في وثائق جوليا.

أعلم أن LazyArrays.jl (والحزم الأخرى؟) يستخدمها بالفعل بشكل أعمى لذا لن يكون اتباع semver جيدًا. لكن مع ذلك ، فهي ليست عامة مثل الوظائف الأخرى.

يتم تصدير mul! من LinearAlgebra ويتم استخدامه على نطاق واسع ، لذا سنضطر بالتأكيد إلى إهماله في هذه المرحلة. إنه لأمر مخز أنه لم يكن لدينا هذا النقاش عندما أصبح A_mul_B! mul! أو على الأقل قبل 0.7 لأنه كان من الأفضل إعادة تسمية الوظيفة.

ماذا عن استخدام mul! الآن وتحديث اسم LinearAlgebra v2.0 عندما يمكننا تحديث stdlibs بشكل منفصل؟

لا يستخدم LazyArrays.jl mul! نظرًا لأنه غير مرن للعديد من أنواع المصفوفات (ويؤدي إلى خطأ بطء في المترجم عند التجاوز بـ StridedArray s). يعطي بناء بديل للشكل

y .= Mul(A, x)

الذي أجده أكثر وصفيًا. نظير 5 حجة هو

y .= a .* Mul(A, x) .+ b .* y

أود أن أجادل لصالح إهمال mul! والانتقال إلى نهج LazyArrays.jl في LinearAlgebra.jl ، ولكن سيكون هذا أمرًا صعبًا.

لا يستخدم LowRankApprox.jl mul! ، لكن يمكنني تغييره لاستخدام طريقة LazyArrays.jl وبالتالي تجنب خطأ المترجم.

حسنا. اعتقدت أنه لم يكن هناك سوى اقتراحين. لكن من الواضح أن هناك ثلاثة مقترحات تقريبًا ؟:

  1. ثلاثة وخمسة وسيطات mul!
  2. ثلاثة وخمسة وسيطات muladd!
  3. ثلاث وسيطات mul! وخمس وسيطات muladd!

(يمكن muladd! addmul! )

كنت أفكر في أننا نقارن 1 و 3. أفهم الآن أن andreasnoack كان يقارن 1 و 2.

أود أن أقول إن 2 ليس خيارًا على الإطلاق لأن الوسيطات الثلاث mul! هي واجهة برمجة تطبيقات عامة وتستخدم على نطاق واسع. ما قصدته بعبارة "واجهة برمجة التطبيقات ليست عامة تمامًا" هو أن الخمس وسيطات mul! غير موثقة .

نعم ، كانت خطتي هي الاحتفاظ بـ mul! (كصيغة 3 arg و ربما 4 نموذج arg). أعتقد أن هذا مفيد نظرًا لأن 3 arg mul! و addmul! سيكون لهما سلوك مختلف ، على سبيل المثال ، إذا كان هناك addmul!(C, A, B, α, β) ، فسنحصل على:

mul!(C, A, B) = addmul!(C, A, B, 1, 0)
mul!(C, A, B, α) = addmul!(C, A, B, α, 0)
addmul!(C, A, B) = addmul!(C, A, B, 1, 1)
addmul!(C, A, B, α) = addmul!(C, A, B, α, 1)

ومع ذلك ، قد لا ترغب في تنفيذها فعليًا بهذه الطريقة في الممارسة العملية ، على سبيل المثال ، قد يكون من الأسهل استخدام 4-arg mul! و addmul! بشكل منفصل ، وتحديد 5-arg addmul! كـ:

addmul!(C, A, B, α, β) = addmul!(C .= β .* C, A, B, α)

صدم!

ومع ذلك ، قد لا ترغب في تنفيذها فعليًا بهذه الطريقة في الممارسة ، على سبيل المثال ، قد يكون من الأسهل استخدام 4-arg mul! و addmul! بشكل منفصل ، وتحديد 5-arg addmul! مثل:
addmul!(C, A, B, α, β) = addmul!(C .= β .* C, A, B, α)

لماذا لا تفعل ذلك بالشكل الأمثل على الفور؟ الهدف من عدم القيام بذلك على هذا النحو هو أنك تحتاج فقط إلى زيارة عناصر C مرة واحدة ، وهو بالتأكيد أكثر كفاءة للمصفوفات الكبيرة. بالإضافة إلى ذلك ، بالكاد أستطيع أن أصدق أن الكود سيكون أطول من خلال تحديد 5-arg addmul! مقابل كل من 4-arg mul! و addmul! بشكل منفصل.

لمعلوماتك لقد قمت بتعديل تطبيق LinearAlgebra _generic_matmatmul! لأخذ 5 وسيطات في LazyArrays: https://github.com/JuliaArrays/LazyArrays.jl/blob/8a50250fc6cf3f2402758088227769cf2de2e053/src/linalg/linalg/

هنا يتم استدعاؤها عبر:

materialize!(MulAdd(α, A, b, β, c)) 

لكن الشفرة الفعلية (في tiled_blasmul! ) سيكون من السهل ترجمتها مرة أخرى إلى LinearAlgebra.

ما الذي يمكن فعله لمحاولة تسريع هذه العملية؟ ستستفيد الأشياء التي أعمل عليها حقًا من واجهة برمجة تطبيقات موحدة لضرب المصفوفة مع إضافة mul + في المكان

يدعم الإصدار الأخير من Strided.jl الآن أيضًا الوسيطة 5 mul!(C,A,B,α,β) ، والإرسال إلى BLAS عندما يكون ذلك ممكنًا ، واستخدام التنفيذ الخاص به (متعدد مؤشرات الترابط) بخلاف ذلك.

Jutho حزمة رائعة! هل هناك خارطة طريق لما هو التالي؟ هل يمكن أن تكون الخطة في النهاية الاندماج مع الجبر الخطي؟

لم يكن هذا في نيتي أبدًا ولكني لا أعارض ذلك إذا طلب ذلك في وقت ما. ومع ذلك ، أعتقد أن استخدامي الليبرالي لوظائف @generated (على الرغم من وجود وظيفة واحدة فقط) في الوظيفة العامة mapreduce قد لا يكون مناسبًا تمامًا لـ Base.

خارطة الطريق الشخصية الخاصة بي: هذه في الغالب عبارة عن حزمة ذات مستوى منخفض لاستخدامها بواسطة الحزم ذات المستوى الأعلى ، أي الإصدار الجديد من TensorOperations وبعض الحزم الأخرى التي أعمل عليها. ومع ذلك ، فإن بعض الدعم الإضافي للجبر الخطي الأساسي سيكون جيدًا (على سبيل المثال ، تطبيق norm على StridedView يعود حاليًا إلى تطبيق بطيء إلى حد ما لـ norm في قاعدة جوليا) وإذا كان لدي الوقت وتعلمت العمل مع وحدات معالجة الرسومات ، فحاول تنفيذ mapreducekernel مقابل GPUArray s.

أعتقد أن الإجماع حتى الآن هو:

  1. يجب أن نحتفظ بـ mul!(C, A, B)
  2. نحتاج إلى _some_ 5-وسيطات دالة من أجل الضرب الداخلي - add C = αAB + βC

أقترح التركيز أولاً على الاسم الذي يجب أن يكون عليه اسم الوظيفة المكونة من 5 وسيطات ومناقشة واجهة برمجة التطبيقات الإضافية لاحقًا (مثل 3- و 4 وسيطات addmul! ). ولكن هذه هي "الميزة" التي نحصل عليها من _ لا _ باستخدام mul! لذلك من الصعب عدم الاختلاط.

andreasnoack هل تم حل مخاوفك بشأن الإهمال / إعادة التسمية من خلال تعليقsimonbyrne أعلاه https://github.com/JuliaLang/julia/issues/23919#issuecomment -431046516؟ أعتقد أنه ليست هناك حاجة للإهمال.

لمعلوماتك ، لقد انتهيت للتو من التنفيذ # 29634. أقدر ما إذا كان شخص على دراية بـ LinearAlgebra يمكنه مراجعته.

أعتقد أنه من الأسهل والأفضل تسمية كل شيء mul! . كما أنه يتجنب الإهمال. إذا كنا نريد حقًا اسمًا مختلفًا ، فإن muladd أفضل.

هناك شيء آخر يجب أخذه في الاعتبار عند مناقشة واجهة برمجة تطبيقات mul! :

عندما اختفى scale! وتم استيعابه في الانتقال 0.6 -> 0.7 ، كنت حزينًا بعض الشيء لأن الضرب القياسي (خاصية للمسافات المتجهة) كان مختلفًا تمامًا عن ضرب الكائنات نفسها (خاصية الجبر ). ومع ذلك ، فقد تبنت تمامًا أسلوب mul! ، وأقدر بشدة القدرة على rmul!(vector,scalar) و lmul!(scalar,vector) عندما لا يكون الضرب القياسي غير تبادلي. لكني الآن كل يوم منزعج أكثر من الاسم غير اليولياني لعمليتين أخريين في الفضاء المتجه: axpy! وتعميمها axpby! . يمكن أيضًا استيعابها في mul! / muladd! / addmul! . على الرغم من أن هذا غريب بعض الشيء ، إذا كان أحد العاملين في A*B عددًا بالفعل ، فلا داعي لعامل عددي إضافي α .
ولكن ربما بعد ذلك ، على غرار

mul!(C, A, B, α, β)

يمكن أن يكون هناك أيضًا

add!(Y, X, α, β)

لاستبدال axpby! .

andreasnoack هل تم حل مخاوفك بشأن الإهمال / إعادة التسمية من خلال تعليقsimonbyrne أعلاه # 23919 (تعليق)؟ أعتقد أنه ليست هناك حاجة للإهمال.

انظر الفقرة الأخيرة من https://github.com/JuliaLang/julia/issues/23919#issuecomment -430952179. ما زلت أعتقد أن إدخال وظيفة جديدة لا يستحق كل هذا العناء. إذا فعلنا ذلك على أي حال ، أعتقد أنه يجب علينا إهمال الوسيطة الخمسة الحالية mul! .

Jutho أعتقد أن إعادة تسمية acp(b)y! إلى add! ستكون فكرة جيدة.

انظر الفقرة الأخيرة من # 23919 (تعليق) . ما زلت أعتقد أن إدخال وظيفة جديدة لا يستحق كل هذا العناء.

نعم ، لقد قرأته وأجبته أن الخمس وسيطات mul! لم يتم توثيقه ولم يكن جزءًا من واجهة برمجة التطبيقات العامة. لذلك ، من الناحية الفنية ، ليست هناك حاجة للإهمال. راجع الفقرة الأخيرة من https://github.com/JuliaLang/julia/issues/23919#issuecomment -430975159 (بالطبع ، سيكون من اللطيف أن يكون هناك إهمال على أي حال ، لذلك قمت بالفعل بتطبيقه في # 29634.)

هنا ، أفترض أن إعلان واجهة برمجة التطبيقات العامة بسبب توثيق توقيع واحد (على سبيل المثال ، mul!(C, A, B) ) لا ينطبق على التوقيعات الأخرى (على سبيل المثال ، mul!(C, A, B, α, β) ). إذا كان الأمر كذلك ، أعتقد أن جوليا و stdlib الخاص بها يكشفان الكثير من العناصر الداخلية. على سبيل المثال ، هذا هو التوقيع الموثق لـ Pkg.add

https://github.com/JuliaLang/julia/blob/0d713926f85dfa3e4e0962215b909b8e47e94f48/stdlib/Pkg/src/Pkg.jl#L76 -L79

بينما التعريف الفعلي هو

https://github.com/JuliaLang/julia/blob/0d713926f85dfa3e4e0962215b909b8e47e94f48/stdlib/Pkg/src/API.jl#L69 -L70

https://github.com/JuliaLang/julia/blob/0d713926f85dfa3e4e0962215b909b8e47e94f48/stdlib/Pkg/src/API.jl#L27 -L33

إذا كان وجود توثيق توقيع واحد على الأقل لـ Pkg.add يشير إلى أن التوقيعات الأخرى هي واجهة برمجة تطبيقات عامة ، فلن يتمكن Pkg.jl من إزالة السلوك بسبب تفاصيل التنفيذ دون التضاد مع الإصدار الرئيسي ، على سبيل المثال: Pkg.add(...; mode = :develop) يعمل Pkg.develop(...) ؛ يتم دعم جميع وسائط الكلمات الأساسية لـ Context! (والتي قد تكون مقصودة بالفعل).

لكن هذا مجرد انطباعي على أي حال. هل تعتبر أن mul!(C, A, B, α, β) كان عامًا مثل mul!(C, A, B) ؟

أعتقد أننا نتحدث عن بعضنا البعض. ما أقوله هو أنني (ما زلت) لا أعتقد أن تقديم وظيفة أخرى يستحق كل هذا العناء. ومن هنا أشير إلى تعليقي السابق. هذا منفصل عن مناقشة إهمال الوسيطات الخمس mul! .

ومع ذلك ، إذا قررنا إضافة دالة أخرى ، فأعتقد أنه سيكون من الأفضل إهمال الوسيطة الخمسة mul! بدلاً من مجرد كسرها. بالطبع ، لا يتم استخدامه بشكل شائع مثل mul! ثلاثي الوسائط ، ولكن لماذا لا يتم إهماله بدلاً من كسره؟

هذا منفصل عن مناقشة إهمال الوسيطات الخمس mul! .

تفسيري للفقرة الأخيرة من تعليقك https://github.com/JuliaLang/julia/issues/23919#issuecomment -430952179 هو أنك أقرت بفوائد simonbyrne المدرجة https://github.com/JuliaLang/julia/issues / 23919 # issuecomment -430809383 لوظيفة جديدة من خمس وسيطات لكنها اعتبرت أنها أقل قيمة مقارنة بالحفاظ على _public API_ (كما ذكرت "إعادة التسمية" و "الإهمال"). لهذا السبب اعتقدت أن التفكير فيما إذا كانت الوسيطة الخمس mul! عامة أم لا مهمة.

لكنك ذكرت أيضًا تبرير وجود "وظيفة إضافية" والتي أفترض أنها ما تشير إليه الآن. هل تجادل بأن الحسابات _C = AB_ و _C = αAB + βC_ متشابهة بدرجة كافية بحيث يمكن أن يصف الاسم نفسه كليهما؟ أنا لا أوافق في الواقع لأنه يمكن أن تكون هناك طرق أخرى لتعميم ثلاث حجج mul! : على سبيل المثال ، لماذا لا mul!(y, A₁, A₂, ..., Aₙ, x) لـ _y = A₁ A₂ ⋯ Aₙ x_ https://github.com/JuliaLang/julia / issues / 23919 # issuecomment -402953987؟

لماذا لا تستنكره بدلا من مجرد كسره؟

كما قلت في التعليقات السابقة ، أوافق على إهمال الوسيطات الخمس mul! هو الشيء الصحيح الذي يجب فعله _ إذا كان علينا تقديم وظيفة أخرى. هذا الرمز موجود بالفعل في PR # 29634 الخاص بي.

هل تجادل بأن العمليات الحسابية C = AB و C = αAB + C متشابهة بدرجة كافية بحيث يمكن أن يصف نفس الاسم كليهما؟

نعم ، لأن الأول هو الأخير فقط بـ β=0 . من العدل القول بأن muladd! / addmul! هو اسم أكثر دقة لـ C = αAB + βC لكن الوصول إلى هناك يتطلب إما تقديم دالة ضرب مصفوفة أخرى ( muladd! / addmul! ) أو إعادة تسمية mul! ولا أعتقد أن الأمر يستحق ذلك الآن. إذا حدث هذا في الربيع ، لكان من الأسهل التفكير في التغيير.

أنا في الواقع لا أوافق لأنه يمكن أن تكون هناك طرق أخرى لتعميم المجلة الثلاثية!:

صادف أن قامت جوليا بتعريف طرق ضرب المصفوفة الموضعية بدون الوسيطات α و β لكن تقليد مضاعفة المصفوفة يعتمد بالفعل على BLAS-3 وهناك دالة ضرب المصفوفة العامة هي C = αAB + βC .

إعادة تسمية mul!

هل تقصد إعادة تسميته في stdlib أو في وحدة المستخدم / رمز المصب؟ إذا كنت تقصد الأول ، فقد تم بالفعل (لـ LinearAlgebra و SparseArrays) في # 29634 لذلك لا أعتقد أنك بحاجة إلى القلق بشأنه. إذا كنت تقصد الأخير ، أعتقد أنه يتلخص مرة أخرى في مناقشة عامة أو لا.

يعتمد تقليد مضاعفة المصفوفة حقًا على BLAS-3

لكن جوليا خرجت بالفعل عن اصطلاح التسمية الخاص بـ BLAS. ألن يكون من الجيد أن يكون لديك اسم وصفي أكثر؟

هل تقصد إعادة تسميته في stdlib أو في وحدة المستخدم / رمز المصب؟

29634 لا يعيد تسمية الوظيفة mul! . يضيف الوظيفة الجديدة addmul! .

لكن جوليا خرجت بالفعل عن اصطلاح التسمية الخاص بـ BLAS.

أنا لا أتحدث عن التسمية. على الأقل ليس بالضبط لأن Fortran 77 لديها بعض القيود التي لا نمتلكها من حيث أسماء الوظائف والإرسال. أنا أتحدث عن ما يتم حسابه. تحسب دالة ضرب المصفوفة العامة في BLAS-3 C = αAB + βC وفي جوليا ، كانت mul! (fka A_mul_B! ).

ألن يكون من الجيد أن يكون لديك اسم وصفي أكثر؟

سيكون ، وقد قلت ذلك عدة مرات. تكمن المشكلة في أنه ليس من الأجمل أن يكون لدينا وظيفتان لضرب المصفوفة تقومان بنفس الشيء في الأساس.

29634 لا يعيد تسمية الوظيفة mul! . يضيف الوظيفة الجديدة addmul! .

ما قصدت قوله هو أنه تمت إعادة تسمية mul! المكون من خمسة وسيطات إلى addmul! .

تكمن المشكلة في أنه ليس من الأجمل أن يكون لدينا وظيفتان لضرب المصفوفة تقومان بنفس الشيء في الأساس.

أشعر أنهما إذا كانوا متشابهين في الأساس أم لا ، فهذا أمر شخصي إلى حد ما. أعتقد أن كلا من _C = αAB + βC_ و _Y = A₁ A₂ ⋯ Aₙ X_ هما تعميم صحيح رياضيًا لـ _C = AB_. ما لم يكن _C = αAB + βC_ هو التعميم الفريد ، لا أعتقد أن الحجة قوية بما يكفي. يعتمد ذلك أيضًا على ما إذا كنت تعرف BLAS API ولست متأكدًا مما إذا كانت هذه هي المعرفة الأساسية لمستخدمي Julia النموذجيين.

أيضًا ، _C = AB_ و _C = αAB + βC_ مختلفان جدًا من الناحية الحسابية من حيث استخدام محتوى C أم لا. إنها معلمة إخراج فقط للأول ومعلمة إدخال-إخراج للأخيرة. أعتقد أن هذا الاختلاف يستحق إشارة بصرية. إذا رأيت أن mul!(some_func(...), ...) و mul! يحتويان على النموذج المكون من خمس وسيطات ، يجب أن أحسب عدد الوسائط (وهو أمر صعب عندما تكون نتيجة استدعاء دالة حيث يتعين عليك مطابقة الأقواس) لمعرفة ما إذا كان some_func يقوم ببعض العمليات الحسابية أو مجرد تخصيص. إذا كان لدينا addmul! فيمكنني أن أتوقع على الفور أن some_func في mul!(some_func(...), ...) يقوم بالتخصيص فقط.

أشعر أنهما إذا كانوا متشابهين في الأساس أم لا ، فهذا أمر شخصي إلى حد ما. أعتقد أن كلاً من C = αAB + βC و Y = A₁ A₂ ⋯ Aₙ X هما تعميم صحيح رياضيًا لـ C = AB. ما لم يكن C = αAB + C هو التعميم الفريد ، لا أعتقد أن الحجة قوية بما يكفي.

قد لا يكون هذا هو التعميم الفريد ، ولكنه تعميم يمكن حسابه بتكلفة متطابقة تقريبًا ، ويشكل بدائية مفيدة لبناء خوارزميات الجبر الخطية الأخرى. في العديد من المناسبات ، كنت أرغب في الحصول على إصدار تجريبي غير صفري عند تنفيذ خوارزميات مختلفة متعلقة بالجبر الخطي ، وكان علي دائمًا الرجوع إلى BLAS.gemm! . لا يمكن بأي حال من الأحوال حساب التعميمات الأخرى مثل تلك التي ذكرتها في لقطة واحدة بدون مؤقتات وسيطة ، لذا فإن الإصدار الموضعي أقل فائدة بكثير. علاوة على ذلك ، فهي ليست مفيدة بشكل عام مثل العمليات البدائية.

يعتمد ذلك أيضًا على ما إذا كنت تعرف BLAS API ولست متأكدًا مما إذا كانت هذه هي المعرفة الأساسية لمستخدمي Julia النموذجيين.

طالما أن الوسيطات الافتراضية α=1 و β=0 ما زالت موجودة ، فإن الحجج الثلاثة mul! ستفعل ما يتوقعه أي مستخدم Julia بشكل معقول بدون خلفية BLAS. للحصول على خيارات أكثر تقدمًا ، يتعين على المرء الرجوع إلى الدليل ، كما يجب على المرء أن يفعل بأي لغة وأي وظيفة. علاوة على ذلك ، فإن هذه المكالمة الفردية mul! لا تحل محل gemm فحسب ، بل تحل أيضًا محل gemv و trmv (وهو أمر غريب بما فيه الكفاية لا يحتوي على α و المعلمات β في واجهة برمجة تطبيقات BLAS) وربما العديد من المعلمات الأخرى.

أوافق على أن BLAS-3 هو التعميم الصحيح من حيث الحساب ويتكون جيدًا. أنا أتطرق إلى تعميم محتمل آخر لمجرد أنني أعتقد أنه ليس "فريدًا بدرجة كافية" لتبرير استخدام نفس الاسم. راجع أيضًا وسيطة الإخراج فقط مقابل المدخلات والمخرجات في الفقرة الأخيرة من https://github.com/JuliaLang/julia/issues/23919#issuecomment -441267056. أعتقد أن الاسم المختلف يجعل قراءة / مراجعة الكود أسهل.

علاوة على ذلك ، فإن هذه المكالمة المنفردة mul! لا تحل محل gemm فحسب ، بل تحل أيضًا محل gemv و trmv (والغريب أنه لا يحتوي على α المعلمات β في واجهة برمجة تطبيقات BLAS) وربما العديد من المعلمات الأخرى.

نعم ، تم تنفيذه بالفعل في # 29634 وهو جاهز للعمل بمجرد تحديد الاسم (والمراجعة)!

أواجه صعوبة في متابعة هذه المحادثة (إنها طويلة ومترامية الأطراف ... آسف!) ، هل الاقتراح الرائد يشبه mul!(C, A, B; α=true, β=false) ؟

لا أعتقد أن الوسيطة الأساسية لكل من α و مطروحة على الطاولة. على سبيل المثال ، رفض andreasnoack وسيطات الكلمات الرئيسية في https://github.com/JuliaLang/julia/issues/23919#issuecomment -365762889. ذكر simonbyrne وسيطات الكلمات الرئيسية في https://github.com/JuliaLang/julia/issues/23919#issuecomment -426881998 لكن اقتراحه الأخير https://github.com/JuliaLang/julia/issues/23919#issuecomment -431046516 موضعي الحجج.

لم نحدد الاسم بعد (على سبيل المثال ، mul! مقابل addmul! مقابل muladd! ) وأعتقد أن هذا هو الموضوع الرئيسي (أو على الأقل هذه أمنيتي).

كيف تحل هذا النوع من الجدل عادة؟ التصويت؟ نخب؟

هل الاقتراح الرئيسي شيء مثل مول! (C ، A ، B ؛ α = صحيح ، β = خطأ)؟

أنا أحب هذا ، ولكن بدون kwargs.

لا أرى الشيء الكلمة الرئيسية. أنا متردد أيضًا في إضافة كلمات رئيسية يونيكود. أعتقد أن الحجج الموضعية مع هذه القيم الافتراضية جيدة. بالنسبة للتصويت القادم ، فإن عملي على mul! عادي. أعتقد أن هذا تعميم لـ mul! وهو محدد ومفيد بما يكفي لعدم الحاجة إلى اسم جديد.

فقط لجمع البيانات (على الأقل في الوقت الحالي) ، لنقم بالتصويت:

ما هو اسم الوظيفة المفضل لديك لـ _C = αAB + βC_؟

  • : +1: mul!
  • : -1: addmul!
  • : ابتسامة: muladd!
  • : تادا: شيء آخر

بالنسبة لي ، يبدو أن addmul! يصف (A+B)C بدلاً من AB + C .

في البداية قمت بالتصويت لـ mul! ثم نظرت إلى العملية وفكرت "إنها تقوم بضرب ثم إضافة ، من الواضح أننا يجب أن نسميها muladd! . الآن لا يمكنني التفكير في تسميتها أي شيء آخر ، حقيقة أنه في مكانه يُشار إليه بوضوح من خلال ! ويبدو أن جزء التحجيم مناسب لـ args.

إنها تقوم بعملية الضرب ثم الإضافة ، من الواضح أننا يجب أن نسميها muladd!

فقط إذا كنت تستخدم القيمة الافتراضية β=true ، ولكن بعد ذلك لأي قيمة أخرى ، يكون الأمر أكثر عمومية مرة أخرى. إذن ما هو الهدف من عدم تسميته mul! ، حيث تمنحك أي قيمة أخرى ثم القيمة الافتراضية β=false شيئًا أكثر عمومية؟ وكيف سترتب الوسيطات مقارنة بـ muladd(x,y,z) = x*y + z ؟ سيكون مربكا إلى حد ما ، أليس كذلك؟

أعتقد أن muladd! له عيب في السبر الوصفي عندما لا يكون كذلك: الاسم الوصفي سيكون شيئًا مثل scalemuladd! لذكر جزء القياس.

لذلك أنا أفضل mul! لأنه لا يوصف بما فيه الكفاية حتى لا يؤدي إلى التوقعات.

ومع ذلك ، فإنني أسمي النسخة البطيئة في LazyArrays.jl MulAdd .

أفضل muladd! على mul! لأنه من الجيد الحفاظ على تمييز وظيفة لا تستخدم أبدًا قيمة C ( mul! ) من وظيفة تستخدمها ( muladd! ).

  • تقنيًا هو ضرب مصفوفة: [AC] * [Bα؛ Iβ] أو ، انظر التعليق أدناه ، [αA βC] * [B ؛ أنا]
  • ~ لدينا بالفعل 5-arg mul! للمصفوفات المتفرقة ، نفس الشيء بالنسبة لـ linalg الكثيف سيكون ثابتًا ~ (ليست وسيطة جديدة)

لذلك أؤيد تسميته mul! .

  • تقنيًا هو ضرب مصفوفة: [AC] * [Bα؛ أنا]

... إذا كان eltype له عملية ضرب تبادلية

... إذا كان eltype تبادليًا.

IIRC من مناقشة مع andreasnoack Julia يعرّف فقط gemm / gemv أنه y <- A * x * α + y * β لأن ذلك منطقي.

haampie هذا جيد أعلم! كما قمت بتطبيقه في الاتجاه المعاكس في # 29634.

هذه مساعدة محدودة ، ولكن

       C = α*A*B + β*C

هي أفضل طريقة يمكنني التوصل إليها للتعبير عن العملية ، وبالتالي ربما يكون الماكرو <strong i="8">@call</strong> C = α*A*B + β*C أو <strong i="10">@call_specialized</strong> ... أو شيء ما على طول هذه الخطوط هو واجهة طبيعية - أيضًا في حالات مماثلة. ثم يمكن استدعاء الوظيفة الأساسية أيا كان.

يحتويmschauer LazyArrays.jl بواسطة dlfivefifty على صيغة رائعة لاستدعاء 5-وسيطة mul! مثل بناء الجملة الخاص بك (والمزيد!).

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

فقط إذا كنت تستخدم القيمة الافتراضية β=true ، ولكن بعد ذلك لأي قيمة أخرى ، يكون الأمر أكثر عمومية مرة أخرى. إذن ما الفائدة من عدم تسميتها mul! ، حيث تمنحك أي قيمة أخرى ثم القيمة الافتراضية β=false شيئًا أكثر عمومية؟ وكيف سترتب الوسيطات مقارنة بـ muladd(x,y,z) = x*y + z ؟ سيكون مربكا إلى حد ما ، أليس كذلك؟

من المؤكد أن هناك بعض التحجيم هناك ولكن من الواضح أن "عظام" العملية تتضاعف وتضاف. سأكون بخير أيضًا مع muladd!(A, B, C, α=true, β=false) لمطابقة توقيع muladd . يجب أن يتم توثيقه بالطبع ، لكن هذا بديهي. إنه نوع ما يجعلني أتمنى أن يأخذ muladd الجزء الإضافي أولاً ، لكن السفينة أبحرت على ذلك.

وكيف سترتب الوسيطات مقارنة بـ muladd(x,y,z) = x*y + z ؟ سيكون مربكا إلى حد ما ، أليس كذلك؟

هذا هو السبب في أنني أفضل addmul! على muladd! . يمكننا التأكد من أن ترتيب الوسائط لا علاقة له بالقيمة العددية muladd . (على الرغم من أنني أفضل muladd! على mul! )

FWIW هنا ملخص للحجج حتى الآن. (حاولت أن أكون محايدًا لكنني مؤيد- muladd! / addmul! لذا ضع ذلك في الاعتبار ...)

الخلاف الرئيسي هو ما إذا كان _C = AB_ و _C = αAB + C_ مختلفان بما يكفي لإعطاء اسم جديد لهذا الأخير.

إنها متشابهة بما فيه الكفاية لأن ...

  1. إنه BLAS-3 وقابل للتكوين بشكل جيد. لذلك ، _C = αAB + βC_ هو تعميم واضح لـ _C = AB_ (https://github.com/JuliaLang/julia/issues/23919#issuecomment-441246606 ، https://github.com/JuliaLang/julia/issues/ 23919 # issuecomment-441312375 ، إلخ.)

  2. _ " muladd! له عيب يبدو وصفيًا عندما لا يكون كذلك: الاسم الوصفي سيكون شيئًا مثل scalemuladd! لذكر جزء القياس." _ --- https://github.com/ JuliaLang / Julia / Issues / 23919 # issuecomment -441819470

  3. _ "من الناحية الفنية هو ضرب مصفوفة: [AC] * [Bα؛ Iβ]" _ --- https://github.com/JuliaLang/julia/issues/23919#issuecomment -441825009

هم مختلفون بما يكفي لأن ...

  1. _C = αAB + βC_ أكثر من مضاعفة (https://github.com/JuliaLang/julia/issues/23919#issuecomment-430809383 ، https://github.com/JuliaLang/julia/issues/23919#issuecomment-427075792، https://github.com/JuliaLang/julia/issues/23919#issuecomment-441813176 ، وما إلى ذلك).

  2. قد يكون هناك تعميمات أخرى mul! مثل Y = A₁ A₂ ⋯ Aₙ X (https://github.com/JuliaLang/julia/issues/23919#issuecomment-402953987 إلخ.)

  3. معلمة الإدخال فقط مقابل معلمة الإدخال والمخرجات: من المربك أن يكون لديك دالة تستخدم البيانات في C بناءً على عدد الوسائط (https://github.com/JuliaLang/julia/issues/23919#issuecomment -441267056 ، https://github.com/JuliaLang/julia/issues/23919#issuecomment-441824982)

سبب آخر يجعل mul! أفضل لأن ...:

  1. مصفوفة متفرقة بها بالفعل. لذلك فهو جيد للتوافق مع الإصدارات السابقة. الوسيطة العكسية: خمسة وسيطات mul! غير موثقة لذلك لا نحتاج إلى اعتبارها واجهة برمجة تطبيقات عامة.

ولماذا muladd! / addmul! أفضل لأن ...:

  1. يمكن أن يكون لدينا "وظائف يدوية" ثلاثية أو أربع وسائط مختلفة مقابل mul! و muladd! / addmul! بشكل منفصل (https://github.com/JuliaLang/julia/issues / 23919 # issuecomment-402953987، https://github.com/JuliaLang/julia/issues/23919#issuecomment-431046516 ، إلخ.). الحجة المضادة: الكتابة mul!(y, A, x, 1, 1) ليست مطولة كثيرًا مقارنة بـ mul!(y, A, x) (https://github.com/JuliaLang/julia/issues/23919#issuecomment-430674934 ، إلخ.)

شكرا على الملخص الموضوعي tkf

سأكون بخير أيضًا مع مولاد! (A ، B ، C ، α = صحيح ، β = خطأ) لمطابقة توقيع مولاد.

آمل أن يكون الإعداد الافتراضي لوظيفة تسمى mulladd! هي β=true . ومع ذلك ، أعتقد أن هذا الترتيب من الوسيطات ، والذي تم إملاءه من muladd ، سيكون مربكًا للغاية بالنسبة إلى mul!(C,A,B)

ربما أكون مخطئًا ، لكنني أعتقد أن معظم الأشخاص / التطبيقات / الكود عالي المستوى (غير راضين بالفعل عن مجرد عامل الضرب * ) يحتاجون إلى mul! . سيتم استخدام القدرة أيضًا على مزج βC ، مع β=1 ( true ) أو خلاف ذلك ، في كود المستوى الأدنى ، من قبل الأشخاص الذين يعرفون أن واجهة برمجة تطبيقات BLAS لمضاعفة المصفوفة تمكن هذه. أعتقد أن هؤلاء الأشخاص سيبحثون عن هذه الوظيفة تحت mul! ، وهي واجهة Julia المنشأة لـ gemm ، gemv ، ... إضافة اسم جديد (وهذا محير ترتيب الحجة المعاكسة) لا يبدو يستحق ذلك ؛ فشلت في رؤية المكسب؟

أعتقد أن هؤلاء الأشخاص سيبحثون عن هذه الوظيفة تحت mul! ، وهي واجهة Julia المنشأة لـ gemm ، gemv ، ... إضافة اسم جديد (وهو أمر محير ترتيب الحجة المعاكسة) لا يبدو يستحق ذلك ؛ فشلت في رؤية المكسب؟

أعتقد أن قابلية الاكتشاف ليست مشكلة كبيرة حيث يمكننا ببساطة ذكر muladd! في mul! docstring. أولئك الذين يتمتعون بمهارات كافية لمعرفة BLAS سيعرفون أين يبحثون عن API ، أليس كذلك؟

فيما يتعلق بالوسيطات الموضعية مقابل الكلمات الرئيسية: لم تتم مناقشتها هنا حتى الآن ولكن أعتقد أن C = αAB + βC مع α كونها مصفوفة قطرية يمكن تنفيذها بكفاءة وسهولة مثل الحجم α . يتطلب هذا الامتداد أنه يمكننا إرسال نوع α وهو أمر مستحيل مع وسيطة الكلمة الأساسية.

أيضًا ، بالنسبة إلى eltype غير التبادلي ، قد ترغب في حساب C = ABα + Cβ بكفاءة عن طريق استدعاء muladd!(α', B', A', β', C') (ترتيب الوسيطة الافتراضي). قد يتطلب الأمر أن تكون قادرًا على الإرسال على أغلفة كسولة Adjoint(α) و Adjoint(β) . (أنا لا أستخدم الأرقام غير التبادلية في جوليا شخصيًا ، لذا من المحتمل أن يكون هذا افتراضيًا للغاية).

أتفق مع وجهة نظر Jutho في أن وظيفة الإضافة المتعددة هذه هي واجهة برمجة تطبيقات ذات مستوى منخفض للمبرمجين المهرة مثل منفذي المكتبة. أعتقد أن القابلية للتوسعة لها أولوية عالية لواجهة برمجة التطبيقات (API) والحجة الموضعية هي السبيل للذهاب.

حجة أخرى لتجنب حجة الكلمات الرئيسية هي ما قاله andreasnoack قبل https://github.com/JuliaLang/julia/issues/23919#issuecomment -365762889:

الأسماء α و β ليست أيضًا بديهية جدًا إلا إذا كنت تعرف BLAS

tkf ، بالتأكيد ، حجتي هي: أن عدد الاستخدامات الفعلية لـ β != 0 سيكون أقل من تلك الخاصة بـ β == 0 ، ولن يفاجأ أولئك الذين يحتاجون إليها عندما يجدون هذا أكثر عمومية السلوك تحت mul! . لذلك ، لا أرى مكاسب فصل هذا تحت اسم جديد ، خاصة وأن ترتيب الوسيطة معطوب (مع muladd! على الأقل). إذا كان يجب أن تكون طريقة جديدة ، فأنا أتعاطف أيضًا مع وسيطتك لـ addmul! .

لن يفاجأ أولئك الذين يحتاجون إليه عندما يجدون هذا السلوك العام قليلاً تحت mul! .

وأنا أتفق مع هذه النقطة.

لذلك ، لا أرى مكاسب من فصل هذا تحت اسم جديد ،

ما لم تر بعض الأضرار ، أعتقد أنه مكسب عالمي لأن هناك أشخاص آخرين يرون الفوائد.

خاصة وأن ترتيب الوسيطة معطل (مع muladd! على الأقل)

أعتقد أنك ستحسب هذا على أنه ضرر وأنا أفهم هذه النقطة. أعتقد فقط أن الفوائد الأخرى لـ muladd! / addmul! أكثر أهمية.

أعتقد أنك ستحسب هذا على أنه ضرر وأنا أفهم هذه النقطة. أعتقد أنها فوائد أخرى لمولد! / addmul! هي أكثر أهمية.

هذا هو الضرر حقًا ، إلى جانب حقيقة أن mul! كان دائمًا نقطة الدخول الوحيدة في العديد من عمليات BLAS المتعلقة بالضرب ، سواء كان ذلك مقيدًا بعدم منح الوصول الكامل إلى α و. والآن مع muladd! ، سيكون هناك نقطتا إدخال مختلفتان ، اعتمادًا على اختلاف طفيف في العملية المطلوبة والتي يمكن التقاطها بسهولة بواسطة وسيطة (وفي الواقع ، يتم التقاطها بواسطة وسيطة في واجهة برمجة تطبيقات BLAS) . أعتقد أنه كان من الخطأ في جوليا في المقام الأول عدم توفير الوصول الكامل إلى واجهة برمجة تطبيقات BLAS (لذا شكرًا لإصلاح ذلكtkf). على الرغم من أنه اصطلاح قديم فظيع لتسمية فورتران ، أعتقد أن هؤلاء الرجال يعرفون سبب قيامهم بالأشياء بهذه الطريقة. ولكن بالمثل ، أعتقد أن هذه المجموعة من العمليات (أي عائلة العمليات ذات المعلمتين المحددة بواسطة α و) تنتمي معًا تحت نقطة دخول واحدة ، كما هو الحال في BLAS.

أكثر حجة مضادة صحيحة من وجهة نظري هي الفرق بين ما إذا كان سيتم الوصول إلى البيانات الأصلية في C لا. ولكن بالنظر إلى حقيقة أن جوليا قد تبنت الضرب بـ false كطريقة لضمان نتيجة صفرية ، حتى عندما يكون العامل الآخر هو NaN ، أعتقد أنه يتم الاهتمام بهذا أيضًا. ولكن ربما يلزم إيصال / توثيق هذه الحقيقة بشكل أفضل (لقد مر وقت طويل منذ أن قرأت الوثائق) ، وقد علمت بها مؤخرًا فقط. (لهذا السبب في KrylovKit.jl ، أطلب وجود طريقة fill! ، لتهيئة نوع مستخدم شبيه بالمتجه مع الأصفار. لكنني الآن أعلم أنه يمكنني فقط rmul!(x,false) بدلاً من ذلك ، لذلك لست بحاجة إلى فرض تطبيق fill! ).

أعتقد أنها فوائد أخرى لمولد! / addmul! هي أكثر أهمية.

دعوني أعكس السؤال ، ما هي هذه الفوائد الأخرى لامتلاك طريقة جديدة؟ لقد قرأت الملخص الخاص بك مرة أخرى ، لكنني لا أرى سوى نقطة الوصول إلى C ، والتي علقت عليها للتو.

لقد ذكرت لزوجتي هذا الصباح أنه كانت هناك محادثة استمرت شهرين في مجتمع جوليا بخصوص تسمية عملية جراحية. اقترحت أن يطلق عليه "فريد"! - لا يوجد اختصار ، لا معنى عميق ، مجرد اسم جيد. فقط ضع هذا هناك نيابة عنها.

جيد أنها تضمنت علامة تعجب! 😄

بادئ ذي بدء ، فقط في حالة حدوث ذلك ، اسمحوا لي أن أوضح أن قلقي يأتي فقط من قابلية قراءة الكود ، وليس قابلية الكتابة أو قابلية الاكتشاف. تكتب الرمز مرة واحدة ولكن تقرأ عدة مرات.

ما هي هذه الفوائد الأخرى من وجود طريقة جديدة؟

كما علقت ، أعتقد أن وسيطة معلمة الإخراج مقابل المدخلات والمخرجات هي الأكثر أهمية. ولكن هذا أحد الأسباب التي تجعلني أعتقد أن _C = αAB + βC_ يختلف عن _C = AB_. أعتقد أيضًا أن الحقيقة البسيطة المتمثلة في اختلافهما بمعنى أن التعبير السابق هو "مجموعة شاملة" صارمة من الثانية تحتاج إلى إشارة مرئية واضحة في الكود. يساعد الاسم المختلف المبرمج المتوسط ​​(أو القليل من المبرمج المتقدم غير المركّز) على الكشط في الكود ويلاحظ أنه يستخدم شيئًا أغرب من mul! .

لقد تحققت للتو من الاستطلاع (تحتاج إلى النقر فوق "تحميل المزيد" أعلاه) مرة أخرى ويبدو أن بعض الأصوات قد انتقلت من mul! إلى muladd! ؟ آخر مرة رأيتها ، كان mul! هو الفائز. دعونا نسجلها هنا قبل أن ينتقلوا: يضحك:

  • mul! : 6
  • addmul! : 2
  • muladd! : 8
  • شيء آخر: 1

بشكل أكثر جدية ، ما زلت أعتقد أن هذه البيانات لا تظهر mul! أو muladd! أكثر وضوحًا من الآخر. (على الرغم من أنه يظهر أن addmul! أقلية: sob :)

يبدو أننا عالقون. كيف نمضي قدما؟

فقط أطلق عليه gemm! بدلاً من ذلك؟

فقط أطلق عليه الجوهرة! في حين أن؟

آمل أن تكون هذه مزحة ... إلا إذا كنت تقترح gemm!(α, A::Matrix, x::Vector, β, y::Vector) = gemv!(α, A, x, β, y) لمتجه المصفوفة *.

هل يمكننا ترك واجهة mul! الموجودة بالفعل (مع مصفوفات متفرقة) في الوقت الحالي حتى نتمكن من دمج العلاقات العامة والحصول على التحسينات ، والقلق بشأن ما إذا كنا نريد إضافة muladd! في علاقات عامة أخرى ؟

ربما يكون واضحًا للجميع هنا ولكني أردت فقط التأكيد على أن التصويت ليس كذلك

  • mul! مقابل muladd!

لكن

  • mul! مقابل ( mul! و muladd! )

أي وجود وظيفتي ضرب متحورتين بدلاً من وظيفة واحدة.

قررت عدم النشر بعد الآن منذ أي وقت قمت فيه بالنشر لصالح mul! ، يبدو أن الأصوات تنتقل من mul! إلى ( mul! و muladd! ).

ومع ذلك ، لدي سؤال؟ إذا ذهبنا مع تصويت الأغلبية الحالي ، ولدينا في الوقت نفسه mul!(C,A,B) و muladd!(A,B,C,α=true,β=true) ، وأريد إعداد PR الذي يحل محل axpy! و axpby! بـ اسم أكثر جوليان add! ، يجب أن يكون add!(y, x, α=true, β=true) أو add!(x, y, α=true, β=true) (حيث تم تغيير y للتوضيح). أو أي شيء آخر؟

في حالة عدم وضوح ذلك ، فإن muladd!(A,B,C) ينتهك اصطلاح الوسيطات المتحولة أولاً .

هل يمكننا ترك واجهة mul! موجودة بالفعل

jebej أعتقد أن حجة "التوافق مع الإصدارات السابقة" تمت مناقشتها على نطاق واسع. ومع ذلك ، فهو لا يقنع أي شخص (بالنظر إلى الاستطلاع ، لست فقط أنا).

تقلق بشأن ما إذا كنا نريد إضافة muladd! في علاقات عامة أخرى؟

من السيء كسر واجهة برمجة التطبيقات العامة. لذلك إذا قلنا mul! فهذا يعني أنه mul! إلى الأبد (على الرغم من أنه من الناحية النظرية يمكن للجبر الخطي أن يصطدم بنسخته الرئيسية لكسر API)

أريد إعداد تصريح إقامة يستبدل axpy! و axpby! باسم جوليان add! ، يجب أن يكون add!(y, x, α=true, β=true) أو add!(x, y, α=true, β=true)

@ جوثو شكرا ، سيكون ذلك رائعا! أعتقد أن اختيار ترتيب الوسيطة سيكون أمرًا سهلاً بمجرد أن نقرر توقيع استدعاء API متعدد الإضافة.

muladd!(A,B,C) ينتهك اصطلاح الوسيطات المتحولة أولاً .

simonbyrne ولكن (كما ذكرت بالفعل في https://github.com/JuliaLang/julia/issues/23919#issuecomment-426881998) ، lmul! و ldiv! وسيطة غير أولية. لذلك أعتقد أننا لسنا بحاجة إلى استبعاد muladd!(A,B,C,α,β) من الاختيار ولكن بدلاً من ذلك نحسبه كنقطة سلبية لهذا التوقيع.

(لكنني أقول إنه استخدم muladd!(α, A, B, β, C) إذا كان لدينا واجهة برمجة تطبيقات "طلب نصي".)

بالمناسبة ، هناك شيء واحد لا أفهمه نتيجة التصويت وهو عدم التماثل بين muladd! و addmul! . إذا كتبت C = βC + αAB ، أعتقد أنه يبدو أن addmul! أكثر طبيعية.

tkf يتعلق الأمر بالعملية التي تقوم بها أولاً. بالنسبة لي ، يقترح addmul! أن تقوم بالإضافة أولاً ، ثم الضرب ، كما في (A+B)C . بالطبع هو شخصي. لكن الأسماء الجيدة يجب أن تروق للحدس.

آه ، لقد فهمت هذه النقطة.

نظرًا لأن هذا لا يزال عالقًا ، فسيحتوي اقتراحي على نمط استخدام يتكون من تعريفات الوظائف مع (الذهاب مع @callexpr للثاني)

@callexpr(C .= β*C + α*A*B) = implementation(C, β, α, A, B)
@callexpr(C .= β*C + A*B) = implementation(C, β, true, A, B)

وربما نموذج أكثر ملاءمة للإرسال (باستخدام @callname للثاني)

function @callname(β*C + A*B)(C::Number, β::Number, A::Number, B::Number)
     β*C + A*B
end

والمكالمات

@callexpr(A .= 2*C + A*B)
@callexpr(2*3 + 3*2)

ولا داعي للقلق (أو معرفة) كيف يقوم callexpr بتحويل العمليات الجبرية إلى اسم دالة فريد (لا يعتمد على رموز الوسيطة ، فقط على العمليات وترتيب العمليات.)
فكرت قليلاً في التنفيذ ويجب أن يكون قابلاً للتنفيذ بشكل جيد.

mschauer أعتقد أن هذا اتجاه مثير للاهتمام. هل يمكنك فتح عدد جديد؟ يمكن لواجهة برمجة التطبيقات التي تقترحها حل العديد من المشكلات الأخرى. أعتقد أنه يحتاج إلى إجراء عملية تصميم دقيقة بدلاً من حل حالة واحدة من المشكلة التي يمكن حلها.

لذلك سمعت إشاعة أن تجميد الميزة 1.1 سيكون الأسبوع المقبل. على الرغم من أن الإصدار الثانوي التالي هو "فقط" أربعة أشهر ، فسيكون من الرائع حقًا أن نحصل عليه في 1.1 ...

على أي حال ، نحتاج أيضًا إلى تحديد توقيع المكالمة (ترتيب الوسائط والكلمة الرئيسية أم لا) قبل دمج العلاقات العامة.

لذلك دعونا نجري التصويت مرة أخرى (حيث وجدت أنه منبه لطيف).

_If_ استخدمنا muladd! لـ _C = ABα + Cβ_ ، ما هو توقيعك المفضل على المكالمة؟

  • : +1: muladd!(C, A, B, α, β)
  • : -1: muladd!(A, B, C, α, β)
  • : ابتسامة: muladd!(C, A, B; α, β) (مثل: +1 :، لكن مع حجة الكلمات المفتاحية)
  • : tada: muladd!(A, B, C; α, β) (مثل: -1 :، لكن مع وسيطات الكلمات الرئيسية)
  • : confused: muladd!(A, B, α, C, β)
  • : القلب: شيء آخر

إذا كان لديك أسماء وسيطات كلمات رئيسية أخرى في الاعتبار ، فقم بالتصويت لتلك التي تستخدم α و β ثم قم بالتعليق على الأسماء الأفضل.

نظرًا لأننا لم نحدد الاسم الذي يجب أن يكون عليه ، نحتاج إلى القيام بذلك مقابل mul! أيضًا:

_If_ استخدمنا mul! لـ _C = ABα + Cβ_ ، ما هو توقيعك المفضل على المكالمة؟

  • : +1: mul!(C, A, B, α, β)
  • : -1: mul!(A, B, C, α, β)
  • : ابتسامة: mul!(C, A, B; α, β) (مثل: +1 :، لكن مع حجة الكلمات المفتاحية)
  • : tada: mul!(A, B, C; α, β) (هذا مستحيل)
  • : confused: mul!(A, B, α, C, β)
  • : القلب: شيء آخر

ملاحظة: نحن لا نغير API الحالي mul!(C, A, B)

ملاحظة: نحن لا نغير API الحالي mul!(C, A, B)

لم أكن قد أولت اهتمامًا كافيًا لهذه الحقيقة - لدينا بالفعل mul! وهذا ما يعنيه ذلك:

mul!(Y, A, B) -> Y

لحساب مصفوفة المصفوفة أو منتج متجه المصفوفة A*B وتخزين النتيجة في Y ، والكتابة فوق القيمة الحالية Y . لاحظ أن Y يجب ألا يكون له اسم مستعار إما مع A أو B .

بالنظر إلى ذلك ، يبدو من الطبيعي جدًا أن يتم توسيع هذا على النحو التالي:

mul!(Y, A, B) -> Y
mul!(Y, A, B, α) -> Y
mul!(Y, A, B, α, β) -> Y

لحساب مصفوفة المصفوفة أو منتج متجه المصفوفة A*B وتخزين النتيجة في Y ، الكتابة فوق القيمة الحالية Y . لاحظ أن Y يجب ألا يكون له اسم مستعار إما بـ A أو B . إذا تم توفير قيمة رقمية ، α ، فسيتم حساب α*A*B بدلاً من A*B . إذا كانت القيمة العددية ، يتم توفير β ، فسيتم حساب α*A*B + β*Y بدلاً من ذلك. ينطبق نفس تقييد الاسم المستعار على هذه المتغيرات.

ومع ذلك، أعتقد أن هناك مصدر قلق كبير مع هذا: على ما يبدو على الأقل وكأنها أمر طبيعي ل mul!(Y, A, B, C, D) لحساب A*B*C*D في المكان إلى Y -وأن اشتباكات فكرة عامة سيئة للغاية مع mul!(Y, A, B, α, β) حساب α*A*B + β*C . علاوة على ذلك ، يبدو لي أن حساب A*B*C*D إلى Y هو شيء سيكون مفيدًا ويمكن القيام به بكفاءة ، وتجنب التخصيصات المتوسطة ، لذلك لا أريد حقًا حظر هذا المعنى .

مع وضع هذا التعميم الطبيعي الآخر لـ mul! في الاعتبار ، إليك فكرة أخرى:

mul!(Y, α, A, B) # Y .= α*A*B

يتناسب هذا مع النموذج العام mul!(out, args...) حيث تقوم بالحساب والكتابة في out بضرب args معًا. إنها تعتمد على الإرسال للتعامل مع α كونها عددية بدلاً من جعلها حالة خاصة - إنها مجرد شيء آخر تقوم بضربه. عندما يكون α عددًا و A و B و Y عبارة عن مصفوفات ، يمكننا الإرسال إلى BLAS للقيام بذلك بكفاءة فائقة. خلاف ذلك ، يمكن أن يكون لدينا تنفيذ عام.

علاوة على ذلك ، إذا كنت في حقل غير تبادلي (على سبيل المثال quaternions) ، فيمكنك التحكم في أي جانب من جوانب القياس بمقدار α يحدث على: mul!(Y, A, B, α) مقياس بواسطة α على اليمين بدلا من اليسار:

mul!(Y, A, B, α) # Y .= A*B*α

نعم ، لا يمكننا استدعاء BLAS من أجل quaternions ، لكنها عامة وربما لا يزال بإمكاننا القيام بذلك بكفاءة معقولة (ربما حتى تحويلها إلى بعض مكالمات BLAS بطريقة ما).

بافتراض أن هذا النهج لـ Y .= α*A*B يصبح السؤال التالي: ماذا عن القياس وزيادة Y ؟ بدأت التفكير في الكلمات الرئيسية الخاصة بذلك ، ولكن بعد ذلك خطر ببالي المجال غير التبادلي الذي كان محرجًا ومحدودًا للغاية. لذلك ، بدأت أفكر في واجهة برمجة التطبيقات هذه بدلاً من ذلك - والذي يبدو غريباً بعض الشيء في البداية ، لكن احمل معي:

mul!((β, Y), α, A, B) # Y .= β*Y .+ α*A*B

غريب بعض الشيء ، لكنه يعمل. وفي الحقل غير التبادلي ، يمكنك طلب مضاعفة Y β على اليمين كما يلي:

mul!((Y, β), α, A, B) # Y .= Y*β .+ α*A*B

بشكل عام بالكامل في مجال غير تبادلي ، يمكنك القياس على اليسار واليمين على النحو التالي:

mul!((β₁, Y, β₂), α₁, A, B, α₂) # Y .= β₁*Y*β₂ + α₁*A*B*α₂

الآن ، بالطبع ، هذا غريب بعض الشيء ولا توجد عملية BLAS لهذا الغرض ، ولكنه تعميم لـ GEMM يتيح لنا التعبير عن الكثير من الأشياء والتي يمكننا إرسالها إلى عمليات BLAS بشكل تافه دون القيام بأي شيء سيئ إذا / آخر الفروع.

يعجبني حقًا اقتراح StefanKarpinski باعتباره استدعاءًا أساسيًا لواجهة برمجة التطبيقات ، لكنني أفكر أيضًا في ما إذا كانت هذه هي الطريقة التي نرغب بها في كشف الأشياء للمستخدمين. IMO ، في النهاية يجب أن تبدو بسيطة ، مثل الماكرو المرتبط:

@affine! Y = β₁*Y*β₂ + α₁*A*B*α₂

ستكون الوظيفة الأساسية بعد ذلك شيئًا مثل يقترح StefanKarpinski .

لكن يجب أن نذهب أبعد من ذلك هنا. أعتقد حقًا أنه إذا قمت بإنشاء واجهة برمجة تطبيقات لها ووظيفة عامة ، فسيقوم شخص ما بإنشاء مكتبة جوليا التي تقوم بذلك بكفاءة ، لذلك أوافق على ألا نلتزم فقط بـ BLAS هنا. أشياء مثل MatrixChainMultiply.jl تقوم بالفعل ببناء DSLs لحسابات المصفوفة المتعددة وتقوم DiffEq بعملها الخاص مع تعبيرات المشغل الأفيني. إذا كان لدينا تمثيل واحد فقط لتعبير أفيني في Base ، فيمكننا تحديد كل عملنا ليكون على نفس الشيء.

dlfivefifty نظرت إلى الجبر الخطي الكسول من قبل ، أعتقد أنه يجب إحياء ذلك هنا حقًا. كان بناء تمثيلات كسولة للبث أمرًا حاسمًا للحصول على عمليات عنصر الحكمة تعمل على مصفوفات مجردة وعلى أجهزة حسابية بديلة. نحتاج إلى نفس الشيء في الجبر الخطي. سيسمح لنا تمثيل التعبيرات الجبرية الخطية بتعريف نواة BLAS جديدة أثناء التنقل من Julia BLAS أو نقل المعادلات إلى GPU / TPU.

تتلخص جميع العمليات الحسابية في الحوسبة العلمية أساسًا في العمليات الجبرية الخطية والعناصر ، لذا فإن وجود وصف عالي المستوى لكليهما يبدو مفيدًا لبناء الأدوات للميتابروغرام واستكشاف التصميمات الجديدة.

يجب أن أفكر أكثر في هذا الاقتراح ، لكن في الوقت الحالي ، سأعلق فقط على أنني لا أعتقد أنك ترغب في حساب A*B*C بدون مؤقت. يبدو لي أنه سيتعين عليك الدفع من خلال الكثير من العمليات الحسابية لتجنب المؤقت.

لا أعتقد أنك ترغب في حساب A*B*C بدون مؤقت.

بالنسبة إلى mul! لديك بالفعل مصفوفة إخراج. لست متأكدًا مما إذا كان ذلك يساعد أم لا. في أي حال ، يبدو وكأنه تفاصيل التنفيذ. تعبر API mul!(Y, A, B, C...) عن ما تريد حسابه وتتيح للتنفيذ اختيار أفضل طريقة للقيام بذلك ، وهو الهدف العام هنا.

يعجبني حقًا اقتراح StefanKarpinski باعتباره استدعاءًا أساسيًا لواجهة برمجة التطبيقات ، لكنني أفكر أيضًا في ما إذا كانت هذه هي الطريقة التي نرغب بها في كشف الأشياء للمستخدمين.

ChrisRackauckas : أعتقد أن الأشياء التي تدخل فيها يمكن ويجب أن يتم استكشافها في حزم خارجية - الكسل ، وكتابة الحساب الذي تريده والسماح لنوع من التحسين بتمرير القطع التي تتطابق مع أنماط جبرية معينة يعرف كيفية تحسينها ، وما إلى ذلك. يبدو استخدام mul! مثل هذا النوع من العمليات العامة ولكن سهلة الفهم التي نريدها على هذا المستوى.

لاحظ أنه لا يوجد جدل حقيقي حول mul!(Y, α, A, B) - يجب أن يعني إلى حد كبير Y .= α*A*B لأن ماذا يعني أيضًا؟ بالنسبة لي ، فإن السؤال الوحيد المطروح هنا هو ما إذا كان استخدام مجموعة مع مصفوفة والكماليات اليسرى و / أو اليمنى طريقة معقولة للتعبير عن رغبتنا في زيادة مصفوفة المخرجات وقياسها. الحالات العامة ستكون:

  1. mul!(Y::Matrx, args...) : Y .= *(args...)
  2. mul!((β, Y)::{Number, Matrix}, args...) : Y .= β*Y + *(args...)
  3. mul!((Y, β)::{Matrix, Number}, args...) : Y .= Y*β + *(args...)
  4. mul!((β₁, Y, β₂)::{Number, Matrix, Number}, args...) : Y .= β₁*Y*β₂ + *(args...)

لن يُسمح بأي شيء آخر للحجة الأولى. يمكن اعتماد هذا باعتباره اصطلاحًا أكثر عمومية للعمليات الأخرى حيث يكون من المنطقي إما الكتابة فوق أو التراكم في مصفوفة الإخراج ، مع دمجها اختياريًا مع القياس.

لم يخطر ببالي "دمج" mul!(out, args...) وواجهة تشبه GEMM! يعجبني قابلية التمدد (ولكن بعد ذلك ابدأ في كتابة الرد أدناه والآن لست متأكدًا ...)

لكن ما يقلقني هو أنه إذا كان من السهل استخدامه كواجهة تحميل زائد. نحتاج إلى الاعتماد على نظام الكتابة للعمل بشكل جيد مع المجموعات المتداخلة. هل تعمل المجموعات المتداخلة مثل المجموعات المسطحة في نظام نوع Julia؟ أتساءل عما إذا كان شيء مثل " Tuple{Tuple{A1,B1},C1,D1} أكثر تحديدًا من Tuple{Tuple{A2,B2},C2,D2} iff Tuple{A1,B1,C1,D1} أكثر تحديدًا من التعليق Tuple{A2,B2,C2,D2} ". وإلا سيكون من الصعب استخدامه كواجهة برمجة تطبيقات للتحميل الزائد.

لاحظ أننا نحتاج إلى إرسال الأنواع العددية لاستخدام إعادة تفسير الاختراق للمصفوفات المعقدة (هذا من PR # 29634 لذلك لا تنتبه إلى اسم الوظيفة):

https://github.com/JuliaLang/julia/blob/fae1a7a3ae646c7ea1c08982976b57096fb0ae8d/stdlib/LinearAlgebra/src/matmul.jl#L157 -L169

مصدر قلق آخر هو أن هذه واجهة محدودة إلى حد ما لمنفذ الرسم البياني الحسابي. أعتقد أن الغرض الرئيسي من واجهة الإضافة المضاعفة هو توفير واجهة برمجة تطبيقات محملة بشكل زائد للسماح لمنفذي المكتبة بتعريف نواة حسابية صغيرة قابلة لإعادة الاستخدام يمكن تنفيذها بكفاءة. هذا يعني أنه يمكننا فقط تنفيذ _C = ABα_ وليس ، على سبيل المثال ، _αAB_ (انظر https://github.com/JuliaLang/julia/pull/29634#issuecomment-443103667). يتطلب دعم _α₁ABα₂_ للنوع الإلكتروني غير التبادلي إما مصفوفة مؤقتة أو زيادة عدد العمليات الحسابية. ليس من الواضح أي مستخدم يريد ومن الأفضل أن يكون هذا قابلاً للتكوين. في هذه المرحلة ، نحتاج إلى تمثيل رسم بياني حسابي منفصل عن آلية التنفيذ. أعتقد أنه من الأفضل استكشاف هذا في الحزم الخارجية (على سبيل المثال ، LazyArrays.jl ، MappedArrays.jl). ومع ذلك ، إذا تمكنا من العثور على استراتيجية تنفيذ تغطي معظم حالات الاستخدام في وقت ما ، فإن استخدام mul! كنقطة دخول رئيسية سيكون منطقيًا. أعتقد أن هذا سبب آخر لتفضيل muladd! ؛ تخصيص مساحة لاستدعاء API المستقبلي.

يجب أن أفكر أكثر في هذا الاقتراح ، لكن في الوقت الحالي ، سأعلق فقط على أنني لا أعتقد أنك ترغب في حساب A B C بدون مؤقت. يبدو لي أنه سيتعين عليك الدفع من خلال الكثير من العمليات الحسابية لتجنب المؤقت.

يمكنك بالفعل إثبات أن أي تقلص لعدد عشوائي من الموترات ، فإن الطريقة الأكثر فاعلية لتقييم الأمر برمته دائمًا هي استخدام الانقباضات الزوجية. لذا فإن ضرب عدة مصفوفات هو مجرد حالة خاصة لذلك ، يجب أن تضربها في أزواج (أفضل ترتيب هو بالطبع مسألة غير تافهة). لهذا السبب أعتقد أن mul!(Y,X1,X2,X3...) ليس بدائيًا مفيدًا. وفي النهاية ، هذا ما أعتقده mul! ، إنها عملية بدائية يمكن للمطورين تحميلها لأنواعهم المحددة. يمكن بعد ذلك كتابة أي عملية أكثر تعقيدًا باستخدام بنية ذات مستوى أعلى ، على سبيل المثال باستخدام وحدات الماكرو ، ويمكن على سبيل المثال إنشاء رسم بياني حسابي ، والذي يتم تقييمه في النهاية عن طريق استدعاء عمليات بدائية مثل mul! . بالطبع ، يمكن أن تكون تلك البدائية عامة بما يكفي لتشمل حالات مثل الحالة غير التبادلية التي يذكرها StefanKarpinski .

وطالما لم يتم تضمين مصفوفة ضرب / انكماش الموتر ، فمن الصحيح أن التفكير من حيث العمليات البدائية ليس مفيدًا جدًا ويمكن أن يكون من المفيد دمج كل شيء معًا مثل البث.

بشكل عام ، أوافق على أنه سيكون من الجيد أن يكون لديك نوع رسم بياني تمثيل / حساب كسول افتراضي في Base ، لكنني لا أعتقد أن mul! هو طريقة إنشائه.

tkf :

لكن ما يقلقني هو أنه إذا كان من السهل استخدامه كواجهة تحميل زائد. نحتاج إلى الاعتماد على نظام الكتابة للعمل بشكل جيد مع المجموعات المتداخلة. هل تعمل المجموعات المتداخلة مثل المجموعات المسطحة في نظام نوع Julia؟

نعم ، كلنا جيدون في هذا المجال. لست متأكدًا من المكان الذي يأتي فيه التداخل ، لكن تمرير بعض الأشياء في tuple يكون بنفس كفاءة تمريرها جميعًا مثل الحجج الفورية - يتم تنفيذها بنفس الطريقة تمامًا.

هذا يعني أنه يمكننا فقط تنفيذ _C = ABα_ وليس ، على سبيل المثال ، _αAB_

أنا محتار ... يمكنك كتابة mul!(C, A, B, α) و mul!(C, α, A, B) . يمكنك حتى كتابة mul!(C, α₁, A, α₂, B, α₃) . يبدو هذا إلى حد بعيد أكثر واجهات برمجة تطبيقات مضاعفة المصفوفة العامة مرونة والتي تم اقتراحها حتى الآن.

مصدر قلق آخر هو أن هذه واجهة محدودة إلى حد ما لمنفذ الرسم البياني الحسابي. أعتقد أن الغرض الرئيسي من واجهة الإضافة المضاعفة هو توفير واجهة برمجة تطبيقات محملة بشكل زائد للسماح لمنفذي المكتبة بتعريف نواة حسابية صغيرة قابلة لإعادة الاستخدام يمكن تنفيذها بكفاءة.

في هذه المرحلة ، نحتاج إلى تمثيل رسم بياني حسابي منفصل عن آلية التنفيذ.

قد يكون هذا هو الحال ، ولكن هذا ليس المكان المناسب لذلك - يمكن بل يجب تطويره في حزم خارجية. كل ما نحتاجه لحل هذه المشكلة المحددة هو واجهة برمجة تطبيقات مضاعفة المصفوفة التي تعمم ما يمكن إرساله إلى عمليات BLAS - وهو إلى حد كبير ما يفعله هذا بالضبط.

تضمين التغريدة

لذا فإن ضرب عدة مصفوفات هو مجرد حالة خاصة لذلك ، يجب أن تضربها في أزواج (أفضل ترتيب هو بالطبع مسألة غير تافهة). لهذا السبب أعتقد أن mul!(Y,X1,X2,X3...) ليس بدائيًا مفيدًا.

ستسمح عملية mul! للتنفيذ باختيار ترتيب الضرب ، وهي خاصية مفيدة. في الواقع ، القدرة على القيام بذلك هي السبب في أننا قمنا بتحليل العملية * كـ n-ary في المقام الأول ونفس المنطق ينطبق أكثر على mul! لأنه إذا كنت تستخدمه ، من المفترض أنك تهتم بدرجة كافية بالأداء.

بشكل عام ، لا يمكنني معرفة ما إذا كنت تجادل أو تعارض اقتراحي مقابل mul! .

لست متأكدًا من المكان الذي يأتي فيه التداخل ، لكن تمرير بعض الأشياء في tuple يكون بنفس كفاءة تمريرها جميعًا مثل الحجج الفورية

لم أكن قلقًا بشأن الكفاءة ، بل بالأحرى غموض في الإرسال والطريقة حيث أن الجبر الخطي الحالي هش إلى حد ما (والذي قد يكون بسبب عدم فهمي لنظام الكتابة ؛ في بعض الأحيان يفاجئني). كنت أذكر مجموعة tuple المتداخلة لأنني اعتقدت أن حل الطريقة يتم من خلال نوع tuple المتقاطع لجميع الوسائط الموضعية. هذا يعطيك مجموعة مسطحة. إذا كنت تستخدم tuple في الوسيطة الأولى ، فسيكون لديك tuple متداخل.

هذا يعني أنه يمكننا فقط تنفيذ _C = ABα_ وليس ، على سبيل المثال ، _αAB_

أنا محتار ... يمكنك كتابة mul!(C, A, B, α) و mul!(C, α, A, B) .

قصدت أن أقول "يمكننا فقط تنفيذ _C = ABα_ بكفاءة مثل _C = AB_ ولا يمكن تنفيذ المرشحين الآخرين مثل _αAB_ بكفاءة في جميع مجموعات أنواع المصفوفات." (أعني بالكفاءة التعقيد الكبير لوقت O.) لست متأكدًا تمامًا من أن هذا هو الحال حقًا ولكن على الأقل بالنسبة للمصفوفة المتفرقة ، هناك خياران آخران خارج.

في هذه المرحلة ، نحتاج إلى تمثيل رسم بياني حسابي منفصل عن آلية التنفيذ.

قد يكون هذا هو الحال ، ولكن هذا ليس المكان المناسب لذلك - يمكن بل يجب تطويره في حزم خارجية.

هذه بالضبط وجهة نظري. أقترح أن أرى واجهة برمجة التطبيقات هذه على أنها كتلة بناء صغيرة لمثل هذا الاستخدام (بالطبع ، هذا ليس الغرض بأكمله). يمكن تنفيذ وتصميم vararg mul! بعد استكشاف الأشخاص لمساحة التصميم في الحزم الخارجية.

الإرسال على أنواع حتى mul! "معطل" بالفعل: هناك نمو اندماجي في تجاوزات الغموض اللازمة للعمل مع أنواع المصفوفات القابلة للتكوين مثل SubArray و Adjoint .

الحل هو استخدام السمات ، ولدى LazyArrays.jl دليل لإصدار مفهوم mul! مع السمات.

لكن هذا نقاش حول التنفيذ أكثر من API. لكن استخدام tuples لتجميع المصطلحات أمر خاطئ: أليس هذا ما يستخدمه نظام الكتابة؟ في هذه الحالة تصل إلى حل LazyArrays.jl.

مول! ستسمح العملية للتنفيذ باختيار ترتيب الضرب ، وهي خاصية مفيدة. في الواقع ، كانت القدرة على القيام بذلك هي السبب في أننا قمنا بإجراء تحليل العملية * كـ n-ary في المقام الأول ونفس المنطق ينطبق أكثر على mul! لأنه إذا كنت تستخدمه ، فمن المفترض أنك تهتم بدرجة كافية بالأداء.

تحليل * كـ n -ary مفيد للغاية. أستخدمه في TensorOperations.jl لتنفيذ الماكرو @tensoropt ، والذي يعمل بالفعل على تحسين أمر الانكماش. وجدت أن إصدارًا من n -ary من mul! أقل فائدة لأن هناك فائدة قليلة ، من منظور الكفاءة ، في توفير مكان مخصص مسبقًا لوضع النتيجة ، إذا كانت كلها وسيطة لا يزال يتعين تخصيص المصفوفات داخل الوظيفة ثم gc'ed. في الواقع ، في TensorOperations.jl ، لاحظ العديد من الأشخاص أن تخصيص فترات زمنية كبيرة هو أحد الأماكن التي يكون فيها أداء Julia's gc سيئًا حقًا (غالبًا ما يؤدي إلى أوقات gc بنسبة 50٪).

لذلك ، سأقصر mul! على ما هو بالفعل عملية بدائية ، كما دعا إلى ذلك أيضًا tkf إذا فهمت بشكل صحيح: ضرب مصفوفتين في مصفوفة ثالثة ، مع احتمال معاملات عددية. نعم ، يمكننا التفكير في الطريقة الأكثر عمومية للقيام بذلك للجبر غير التبادلي ، ولكن في الوقت الحالي أعتقد أن الحاجة الفورية هي الوصول المريح إلى الوظيفة التي توفرها BLAS (gemm ، gemv ، ...) التي حصلت عليها Julia mul! غلاف يفتقر إلى

أنا لا أكره اقتراحك باستخدام tuples ، لكن يمكنني توقع حدوث ارتباك محتمل
يبدو أن التقييد من الحالة 4 إلى الحالة 2 من 3 يتضمن قيمًا افتراضية β₁ = 1 و β₂ = 1 (أو في الواقع true ). ولكن بعد ذلك ، إذا لم يتم تحديد أي منهما ، فهذا يعني فجأة β₁ = β₂ = 0 ( false ). بالتأكيد ، تختلف الصيغة قليلاً ، نظرًا لأنك تكتب mul!(Y, args...) ، وليس mul!((Y,), args...) . في النهاية ، إنها مسألة توثيق ، لذلك أردت فقط أن أشير إلى ذلك.

إذن باختصار ، لا ، أنا لا أعارض هذه البنية حقًا ، على الرغم من أنها نوع جديد من النموذج الذي يتم تقديمه ، ومن المحتمل أيضًا اتباعه في أماكن أخرى. ما أعارضه هو الرغبة على الفور في تعميم هذا على مضاعفة عدد عشوائي من المصفوفات ، والتي ، كما ذكرنا أعلاه ، لا أرى فائدة منها.

dlfivefifty : لكن هذا نقاش حول التنفيذ أكثر من API. لكن استخدام tuples لتجميع المصطلحات أمر خاطئ: أليس هذا ما يستخدمه نظام الكتابة؟ في هذه الحالة تصل إلى حل LazyArrays.jl.

لكننا لن نذهب إلى المصفوفات البطيئة الكاملة هنا - هناك بالفعل LazyArrays لذلك. في غضون ذلك ، نحتاج إلى طريقة ما للتعبير عن مقياس Y . يبدو استخدام tuples أسلوبًا بسيطًا وخفيف الوزن للتعبير عن هذا القدر الصغير من البنية. هل لدى احد منكم اقتراحات أخرى؟ يمكن أن يكون لدينا lscale و / أو rscale كلمات رئيسية لـ β₁ و β₂ ، لكن هذا لا يبدو أكثر أناقة وسنفقد القدرة على ذلك ، وهو أمر ليس بالغ الأهمية ولكن من الجيد امتلاكه.

Jutho : لذلك ، mul! على ما هو بالفعل عملية بدائية ، كما دعا إلى ذلك أيضًا tkf إذا فهمت بشكل صحيح: ضرب مصفوفتين في مصفوفة ثالثة ، مع احتمال معاملات عددية. نعم ، يمكننا التفكير في الطريقة الأكثر عمومية للقيام بذلك للجبر غير التبادلي ، ولكن في الوقت الحالي أعتقد أن الحاجة الفورية هي الوصول المريح إلى الوظيفة التي توفرها BLAS (gemm ، gemv ، ...) التي حصلت عليها Julia mul! غلاف يفتقر إلى

أنا بخير مع تحديد مجموعة فرعية صغيرة فقط من العمليات مقابل mul! ، وربما حتى تلك التي تتوافق هيكليًا مع مكالمات BLAS الصالحة. ممكن حدوثه:

# gemm: alpha = 1.0, beta = 0.0
mul!(Y::Matrix, A::Matrix, B::Matrix) # gemm! Y, A

# gemm: alpha = α, beta = 0.0 (these all do the same thing for BLAS types)
mul!(Y::Matrix, α::Number, A::Matrix, B::Matrix)
mul!(Y::Matrix, A::Matrix, α::Number, B::Matrix)
mul!(Y::Matrix, A::Matrix, B::Matrix, α::Number)

# gemm: alpha = α, beta = β (these all do the same thing for BLAS types)
mul!((β::Number, Y::Matrix), α::Number, A::Matrix, B::Matrix)
mul!((β::Number, Y::Matrix), A::Matrix, α::Number, B::Matrix)
mul!((β::Number, Y::Matrix), A::Matrix, B::Matrix, α::Number)
mul!((Y::Matrix, β::Number), α::Number, A::Matrix, B::Matrix)
mul!((Y::Matrix, β::Number), A::Matrix, α::Number, B::Matrix)
mul!((Y::Matrix, β::Number), A::Matrix, B::Matrix, α::Number)

# gemm: alpha = α, beta = β₁*β₂ (these all do the same thing for BLAS types)
mul!((β₁::Number, Y::Matrix, β₂::Number), α::Number, A::Matrix, B::Matrix)
mul!((β₁::Number, Y::Matrix, β₂::Number), A::Matrix, α::Number, B::Matrix)
mul!((β₁::Number, Y::Matrix, β₂::Number), A::Matrix, B::Matrix, α::Number)

الى أي نهاية؟ لماذا نسمح بالكثير من الاختلاف في كيفية التعبير عن عمليات BLAS؟

  1. لأنه يسمح للناس بالتعبير عن نواياهم - إذا كانت النية هي الضرب على اليسار أو اليمين أو كليهما ، فلماذا لا نسمح للناس بالتعبير عن ذلك واختيار التنفيذ الصحيح؟

  2. يمكن أن يكون لدينا احتياطات عامة تفعل الشيء الصحيح حتى بالنسبة لأنواع العناصر غير التبادلية.

بيت القصيد من هذه المشكلة هو الحصول على تعميم لضرب المصفوفة الموضعي الذي يشتمل على الأحجار الكريمة! بينما تكون أكثر عمومية من الأحجار الكريمة !. بخلاف ذلك ، لماذا لا تستمر في كتابة gemm! ؟

لكننا لن نذهب إلى المصفوفات البطيئة الكاملة هنا

أنا لا أقول "المصفوفات البطيئة الكاملة" ، بل أقترح الكسل بنفس المعنى مثل Broadcasted ، والذي يتم إزالته في النهاية في وقت التجميع. في الأساس ، أود إضافة Applied لتمثيل تطبيق كسول لوظيفة وبدلاً من استخدام tuples (التي لا تحتوي على سياق) سيكون لديك شيء مثل

materialize!(applied(+, applied(*, α, A, B), applied(*, β, C)))

قد يكون هذا مغطى بالسكر مثل ترميز البث .* لجعله أكثر قابلية للقراءة ، لكنني أعتقد أن هذا واضح على الفور ما هو مطلوب ، على عكس الاقتراح القائم على tuple.

StefanKarpinski ، كما قيل من قبل ، أنا أوافق بالتأكيد على أنه يجب علينا التفكير في واجهة تكون برهانًا في المستقبل وتعمم بشكل صحيح على أنواع الأرقام الأخرى. المشكلة الوحيدة في اعتقادي هي أن قائمتك ليست كاملة. من حيث المبدأ يمكن أن يكون لديك:

mul!((β₁::Number, Y::Matrix, β₂::Number), α₁::Number, A::Matrix, α₂::Number, B::Matrix, α₃::Number)

وجميع الإصدارات المختصرة منها ، أي إذا كانت جميع الوسائط العددية الخمس غائبة ، فهذا يعني أن 2 ^ 5 = 32 احتمالًا مختلفًا. وهذا مقترن بجميع احتمالات المصفوفات أو المتجهات المختلفة.

أتفق مع dlfivefifty على أن اتباع نهج يشبه البث أكثر جدوى.

نعم ، أدركت أنني استبعدت بعض الخيارات ، لكن 32 طريقة لا تبدو مجنونة بالنسبة لي ، بعد كل شيء لا يتعين علينا كتابتها يدويًا. إن إضافة "نظام يشبه البث" أو نظام تقييم كسول يتيح لنا كتابة materialize!(applied(+, applied(*, α, A, B), applied(*, β, C))) يبدو أنه إضافة أكبر بكثير وطريقة خارج نطاق هذه المشكلة. كل ما نريده هو طريقة ما للتهجئة العامة لضرب المصفوفة التي تعتبر عامة وتتيح لنا الإرسال إلى BLAS. إذا لم نتمكن جميعًا من الاتفاق على ذلك ، فأنا أميل إلى السماح للأشخاص بالاستمرار في الاتصال بـ gemm! مباشرة.

نعم ، ربما هذا صحيح ؛ افترضت أنه سيكون من الأسهل استخدام الحجج العددية في الخلف ، لتوفير الإعدادات الافتراضية بسهولة. ولكن لو كان مع بعض @eval metaprogramming يمكننا بسهولة توليد جميع التعاريف 32، وهذا جيد على حد سواء. (ملاحظة ، كما تعلم بالتأكيد ، mul ليس فقط gemm! ولكن أيضًا gemv و trmm و ...).

اسمحوا لي أن أضيف أنه ليس مجرد غلاف BLAS. هناك طرق أخرى متخصصة لجوليا نقية في stdlib. من المهم أيضًا أن يكون هذا بمثابة واجهة برمجة تطبيقات محملة بشكل زائد: يمكن لمؤلفي الحزم تحديد mul! لأنواع المصفوفة الخاصة بهم.

أعتقد أن هذا هو موقفي:

  1. قد ندعم أيضًا mul!(C, A, B, a, b) الآن نظرًا لأنه موجود بالفعل في SparseArrays.jl
  2. لا ينبغي أن نفعل أي شيء آخر لأن الإرسال على أنواع المصفوفات لا يتسع بشكل جيد. (بصفتي مشرفًا على BandedMatrices.jl و BlockArrays.jl و LowRankApprox.jl وما إلى ذلك ، يمكنني أن أذكر ذلك من خلال التجربة.)
  3. يعمل التصميم المستند إلى السمات بشكل جيد ، ولكن سيكون من الأفضل الدخول بشكل كامل والقيام ببث مثل Applied ، نظرًا لأن نمط التصميم قد تم إنشاؤه بالفعل. سيتعين على هذا الانتظار حتى Julia 2.0 ، مع استمرار تطوير نموذج أولي في LazyArrays.jl يناسب احتياجاتي.

dlfivefifty هل تعتقد أن صعوبة توضيح mul!((Y, β), α, A, B) API تساوي mul!(Y, A, B, α, β) ؟ التفكير في أغلفة المصفوفات مثل Transpose يقدم الصعوبة ، بما في ذلك الأصوات 2 و 3-tuples مثل زيادة الصعوبة أكثر (على الرغم من أنني أعرف أن tuple هي حالة خاصة في نظام نوع Julia).

  1. قد ندعم أيضًا mul!(C, A, B, a, b) الآن نظرًا لأنه موجود بالفعل في SparseArrays.jl

حقيقة أن شخصًا ما قرر أن mul!(C, A, B, a, b) يجب أن يعني C .= b*C + a*A*B دون التفكير في الأمر بالكامل ، بالتأكيد ليس سببًا جيدًا لمضاعفة هذا الأمر. إذا كان mul! هو الإصدار الموضعي من * فأنا لا أرى كيف يمكن أن يعني mul!(out, args...) أي شيء بخلاف out .= *(args...) . بصراحة ، هذه هي الطريقة التي ينتهي بها بك الأمر مع نظام فوضوي من واجهات برمجة التطبيقات غير المتسقة المدروسة بشكل سيء والتي لا توجد إلا عن طريق الصدفة التاريخية. لا يتم تصدير الوظيفة mul! من SparseArrays _و_ هذه الطريقة المعينة غير موثقة ، لذلك هذا هو السبب الأكثر واهية لترسيخ طريقة غير مدروسة ربما تمت إضافتها فقط لأن الوظيفة لم تكن عامة! أقترح أن نتراجع عن هذا الخطأ ونحذف / نعيد تسمية هذه الطريقة mul! بدلاً من ذلك.

من بقية هذه المناقشة ، يبدو أننا لا ينبغي أن نفعل أي شيء آخر لأن جميع أصحاب المصلحة يريدون القيام بشيء مربي الحيوانات بسمات و / أو كسل خارج المكتبة القياسية. أنا بخير مع ذلك لأن حذف الأشياء أمر جميل دائمًا.

من بقية هذه المناقشة ، يبدو أننا لا ينبغي أن نفعل أي شيء آخر لأن جميع أصحاب المصلحة يريدون القيام بشيء مربي الحيوانات بسمات و / أو كسل خارج المكتبة القياسية. أنا بخير مع ذلك لأن حذف الأشياء أمر جميل دائمًا.

يبدو أنك سئمت قليلاً ، وهذا أمر مفهوم. ومع ذلك ، لا أعتقد أن هذا الاستنتاج صحيح. إذا كنت واثقًا من إمكانية تنفيذ الاقتراح الحالي بطريقة قابلة للتطوير ولا تزال تجعل من الملائم لمطوري الحزم تحميل هذا التعريف لأنواع المصفوفة والمتجهات الخاصة بهم (كما هو مذكور فيtkf) ، فسيكون ذلك طريقة رائعة إلى الأمام.

على وجه الخصوص ، أعتقد أن مطوري الحزم يحتاجون فقط إلى تنفيذ:

mul!((β₁, Y::MyVecOrMat, β₂), α₁, A::MyMat, α₂, B:: MyVecOrMat, α₃)

وربما ، على سبيل المثال ،

mul!((β₁, Y::MyVecOrMat, β₂), α₁, A::Adjoint{<:MyMat}, α₂, B:: MyVecOrMat, α₃)
...

بينما تهتم قاعدة جوليا (أو بالأحرى مكتبة LinearAlgebra القياسية) بمعالجة جميع القيم الافتراضية وما إلى ذلك.

أعتقد أن مطوري الحزم يحتاجون فقط إلى تنفيذ:

mul!((β₁, Y::MyVecOrMat, β₂), α₁, A::MyMat, α₂, B:: MyVecOrMat, α₃)

أود أن أقترح توثيق

mul!((Y, β), A, B, α)

كتوقيع ليتم تحميلها فوق طاقتها. هذا لأن المواقع الأخرى لـ α تغير تعقيد وقت O الكبير. انظر: https://github.com/JuliaLang/julia/pull/29634#issuecomment -443103667. هذا يعطي الأرقام غير التبادلية معاملة غير من الدرجة الأولى. لكن AFAICT لا أحد هنا يستخدم بالفعل أرقامًا غير تبادلية وأعتقد أننا يجب أن ننتظر حتى تكون هناك حاجة فعلية.

أحد الأشياء التي أحبها في نهج mul!((Y, β), α::Diagonal, A, B) لـ _some_ نوع المصفوفة A (على سبيل المثال ، Adjoint{_,<:SparseMatrixCSC} ) دون تغيير تعقيد الوقت . (هذا مهم لطلبي). بالطبع ، يتطلب السير بهذه الطريقة مزيدًا من المناقشة في واجهة برمجة التطبيقات ، خاصةً حول كيفية الاستعلام عن وجود طريقة متخصصة. لا يزال ، وجود فرصة لتوسيع API أمر رائع.

إذا أوضح شخص ما قلقي بشأن غموض الطريقة ، فسأكون جميعًا مع نهج المجموعة تلو الأخرى.

هذا لأن مواقع أخرى لـ α تغير تعقيد وقت O الكبير.

هل هذا شيء مصفوفة متفرقة على وجه التحديد؟ أنا لا أجادل تمامًا ، لا سيما بالنسبة للمصفوفات الكثيفة. في التطبيق الذي ترتبط به ، تظهر حالة يكون فيها α بين A و B ؟

أعتقد أن مطوري الحزم يحتاجون فقط إلى التنفيذ ...

هذا مبالغة في التبسيط. لنفترض أن لدينا مصفوفة تتصرف مثل مصفوفة متسلسلة ، مثل PseudoBlockMatrix من BlockArrays.jl. لدعم gemm! نحتاج إلى تجاوز كل تبديل لـ PseudoBlockMatrix بـ (1) نفسه ، (2) StridedMatrix ، (3) Adjoint s لنفسه ، (4) Transpose s لنفسه ، (5) Adjoint s من StridedMatrix ، (6) Transpose s من StridedMatrix ، وربما آخرين. هذا بالفعل 6 ^ 3 = 216 مجموعة مختلفة. ثم تريد دعم trmm! وعليك أن تفعل الشيء نفسه مع UpperTriangular و UnitUpperTriangular ومساعداتهم وتنقلاتهم وما إلى ذلك. ثم gsmm! Symmetric و Hermitian .

لكن في العديد من التطبيقات ، لا نريد فقط العمل مع المصفوفات ، ولكن أيضًا مع طرق العرض الفرعية الخاصة بهم ، خاصةً لمصفوفات الكتلة حيث نريد العمل مع الكتل. نحتاج الآن إلى إضافة كل تباعد في وجهات النظر الخاصة بالمصفوفة مع المجموعات الست أعلاه.

الآن لدينا الآلاف من التجاوزات ، بما في ذلك StridedMatrix ، وهو نوع اتحاد معقد للغاية. هذا كثير جدًا بالنسبة للمترجم ، مما يجعل الوقت using يستغرق أكثر من دقائق ، بدلاً من ثوانٍ.

في هذه المرحلة ، يدرك المرء أن mul! ، وبالتالي الامتدادات المقترحة mul! ، معيبة حسب التصميم ، لذا يجب على مطوري الحزم ألا يهتموا بها. لحسن الحظ ، يوفر LazyArrays.jl حلاً مؤقتًا باستخدام السمات.

لذلك أتفق نوعًا ما مع StefanKarpinski في مجرد ترك الأشياء كما هي حتى يتم متابعة إعادة تصميم أكثر جوهرية ، حيث إن بذل الجهد على شيء معيب في التصميم لا يعد استخدامًا جيدًا للوقت.

dlfivefifty ، كنت أشير فقط إلى كيفية معالجة الحجج العددية. جميع التعقيدات مع أنواع المصفوفات المختلفة الموجودة حاليًا مقابل mul!(C,A,B) ستبقى بالطبع.

هذا لأن مواقع أخرى لـ α تغير تعقيد وقت O الكبير.

هل هذا شيء مصفوفة متفرقة على وجه التحديد؟ أنا لا أجادل تمامًا ، لا سيما بالنسبة للمصفوفات الكثيفة. في التطبيق الذي ترتبط به ، تظهر حالة يكون فيها α بين A و B ؟

Jutho أعتقد بشكل عام أنه لا يمكنك وضع α في موضع الحلقة الداخلية. على سبيل المثال ، في هذه الحالة يمكنك دعم α₁*A*B*α₃ لكن ليس A*α₂*B

https://github.com/JuliaLang/julia/blob/11c5680d5620b0b64420055e8474a2b8cf757010/stdlib/LinearAlgebra/src/matmul.jl#L661 -L670

أعتقد أن على الأقل α₁ أو α₂ في α₁*A*α₂*B*α₃ يجب أن يكون 1 لتجنب زيادة تعقيد الوقت المقارب.

dlfivefifty ولكن حتى LazyArrays.jl يحتاج إلى بعض الوظائف البدائية للإرسال إليها ، أليس كذلك؟ ما أفهمه هو أنه يحل مشكلة "إرسال الجحيم" ولكنه لا يقلل من عدد "نواة" الحساب التي يتعين على الأشخاص تنفيذها.

لا ، ليس هناك "بدائي" بنفس الطريقة التي لا تحتوي على "بدائية" Broadcasted . لكن نعم في الوقت الحالي لا يحل هذا السؤال "النواة". أعتقد أن الخطوة التالية هي إعادة تصميمه لاستخدام نوع كسول Applied مع ApplyStyle . ثم قد يكون هناك MulAddStyle للتعرف على العمليات المشابهة لـ BLAS ، بطريقة لا يهم هذا الترتيب.

سأطلق على materialize! أو copyto! كلمة بدائية. على الأقل هو حجر الأساس لآلية البث. وبالمثل ، أفترض أن LazyArrays.jl يضطر إلى خفض تمثيله البطيء إلى وظائف ذات حلقات أو ccall s إلى مكتبات خارجية في وقت ما ، أليس كذلك؟ هل سيكون سيئًا إذا كان اسم هذه الوظيفة هو mul! ؟

هذا مبالغة في التبسيط. لنفترض أن لدينا مصفوفة تتصرف مثل مصفوفة متسلسلة ، مثل PseudoBlockMatrix من BlockArrays.jl. لدعم جوهرة بالكامل! نحن بحاجة إلى تجاوز كل تبديل لـ PseudoBlockMatrix مع (1) نفسها ، (2) StridedMatrix ، (3) Adjoints نفسها ، (4) عمليات تبديل نفسها ، (5) Adjoints of StridedMatrix ، (6) Transposes of StridedMatrix ، وربما أخرى . هذا بالفعل 6 ^ 3 = 216 مجموعة مختلفة. ثم تريد دعم trmm! وعليك أن تفعل الشيء نفسه مع UpperTriangular و UnitUpperTriangular وملحقاتها وتبديلها وما إلى ذلك. ثم gsmm! مع متماثل و Hermitian.
لكن في العديد من التطبيقات ، لا نريد فقط العمل مع المصفوفات ، ولكن أيضًا مع طرق العرض الفرعية الخاصة بهم ، خاصةً لمصفوفات الكتلة حيث نريد العمل مع الكتل. نحتاج الآن إلى إضافة كل تباعد في وجهات النظر الخاصة بالمصفوفة مع المجموعات الست أعلاه.
الآن لدينا الآلاف من التجاوزات ، بما في ذلك StridedMatrix ، وهو نوع اتحاد معقد للغاية. هذا كثير جدًا بالنسبة للمترجم ، مما يجعل وقت الاستخدام يستغرق دقائق بدلاً من ثوانٍ.

أنا أوافق بالتأكيد على أن الاتحاد الحالي من النوع StridedArray هو عيب كبير في التصميم. لقد دعمت محاولتك لإصلاح هذا في مرحلة ما.

مرة أخرى في Strided.jl ، أقوم بتطبيق mul! فقط عندما تكون جميع المصفوفات المعنية من النوع المخصص الخاص بي (Abstract)StridedView ، عندما يكون هناك بعض الاختلاط في أنواع A و B و C ، أسمح لجوليا الأساس / الجبر الخطي يتعامل مع هذا. بالطبع ، سيتم استخدام هذا في بيئة ماكرو @strided ، والتي تحاول تحويل جميع أنواع Base الممكنة إلى النوع StridedView . هنا ، يمكن أن يمثل StridedView عروض فرعية ، وتنقلات ومساعدات ، وإعادة تشكيل معينة ، وكلها من نفس النوع (حدودي). بشكل عام ، يبلغ رمز الضرب الكامل حوالي 100 سطر:
https://github.com/Jutho/Strided.jl/blob/master/src/abstractstridedview.jl#L46 -L147
يتم تنفيذ احتياطي جوليا الأصلي في حالة عدم تطبيق BLAS باستخدام وظيفة mapreducedim! الأكثر عمومية التي توفرها تلك الحزمة ، ولا تقل كفاءة عن تلك الموجودة في LinearAlgebra ؛ ولكنه أيضًا متعدد الخيوط.

أعتقد أن على الأقل α₁ أو α₂ في α₁*A*α₂*B*α₃ يجب أن يكون 1 لتجنب زيادة التعقيد الزمني المقارب.

tkf ، سأفترض أنه إذا كانت هذه المعاملات العددية تأخذ قيمة افتراضية one(T) ، أو الأفضل من ذلك ، true ، فإن التكاثر المستمر وتحسينات المترجم ستقضي تلقائيًا على هذا الضرب. في معظم الحلقة الداخلية عندما يكون الأمر كذلك. لذلك سيكون من الملائم فقط تحديد الشكل الأكثر عمومية.

لست متأكدًا مما إذا كان بإمكاننا الاعتماد على الانتشار المستمر للتخلص من جميع عمليات الضرب بمقدار 1 ( true ). على سبيل المثال ، قد يكون النوع eltype Matrix . في هذه الحالة ، أعتقد أن true * x (حيث x::Matrix ) يجب أن ينشئ نسخة مخصصة كومة من x . هل تستطيع جوليا أن تفعل بعض السحر للقضاء على ذلك؟

Jutho أعتقد أن هذا المعيار يُظهر أن جوليا لا تستطيع التخلص من المضاعفات المتوسطة في بعض الحالات:

function simplemul!((β₁, Y, β₂), α₁, A, α₂, B, α₃)
    <strong i="7">@assert</strong> size(Y, 1) == size(A, 1)
    <strong i="8">@assert</strong> size(Y, 2) == size(B, 2)
    <strong i="9">@assert</strong> size(A, 2) == size(B, 1)
    <strong i="10">@inbounds</strong> for i in 1:size(A, 1), j = 1:size(B, 2)
        acc = zero(α₁ * A[i, 1] * α₂ * B[1, j] * α₃ +
                   α₁ * A[i, 1] * α₂ * B[1, j] * α₃)
        for k = 1:size(A, 2)
            acc += A[i, k] * α₂ * B[k, j]
        end
        Y[i, j] = α₁ * acc * α₃ + β₁ * Y[i, j] * β₂
    end
    return Y
end

function simplemul!((Y, β), A, B, α)
    <strong i="11">@assert</strong> size(Y, 1) == size(A, 1)
    <strong i="12">@assert</strong> size(Y, 2) == size(B, 2)
    <strong i="13">@assert</strong> size(A, 2) == size(B, 1)
    <strong i="14">@inbounds</strong> for i in 1:size(A, 1), j = 1:size(B, 2)
        acc = zero(A[i, 1] * B[1, j] * α +
                   A[i, 1] * B[1, j] * α)
        for k = 1:size(A, 2)
            acc += A[i, k] * B[k, j]
        end
        Y[i, j] = acc * α + Y[i, j] * β
    end
    return Y
end

fullmul!(Y, A, B) = simplemul!((false, Y, false), true, A, true, B, true)
minmul!(Y, A, B) = simplemul!((Y, false), A, B, true)

using LinearAlgebra
k = 50
n = 50
A = [randn(k, k) for _ in 1:n, _ in 1:n]
B = [randn(k, k) for _ in 1:n]
Y = [zeros(k, k) for _ in 1:n]
<strong i="15">@assert</strong> mul!(copy(Y), A, B) == fullmul!(copy(Y), A, B) == minmul!(copy(Y), A, B)

using BenchmarkTools
<strong i="16">@btime</strong> mul!($Y, $A, $B)     # 63.845 ms (10400 allocations: 99.74 MiB)
<strong i="17">@btime</strong> fullmul!($Y, $A, $B) # 80.963 ms (16501 allocations: 158.24 MiB)
<strong i="18">@btime</strong> minmul!($Y, $A, $B)  # 64.017 ms (10901 allocations: 104.53 MiB)

مقياس جيد. كما أنني لاحظت بالفعل أنه لن يلغي هذه التخصيصات من خلال بعض التجارب المماثلة. في مثل هذه الحالات ، قد يكون من المفيد تحديد الغرض الخاص One النوع المفرد الذي يعرّف فقط *(::One, x::Any) = x و *(x::Any, ::One) = x ، ولا يحتاج أي نوع مستخدم إلى الآن. ثم القيمة الافتراضية ، على الأقل لـ α₂ ، يمكن أن تكون One() .

آه ، نعم ، هذا ذكي! اعتقدت في البداية أنني الآن موافق على دعم α₁ * A * α₂ * B * α₃ ولكن بعد ذلك أعتقد أنني وجدت مشكلة أخرى: إنه أمر غامض ما يجب علينا فعله عندما (على سبيل المثال) A مصفوفة من المصفوفة و α₁ مصفوفة. لن تكون مشكلة إذا _لا _ أبدًا _ ندعم الوسيطات غير العددية في α المواضع. ومع ذلك ، فإنه يجعل من المستحيل تقديم Y .= β₁*Y*β₂ + *(args...) كنموذج عقلي لـ mul!((β₁, Y, β₂), args...) . علاوة على ذلك ، سيكون من الرائع حقًا أن يتم تمرير المصفوفات القطرية إلى α₁ أو α₂ حيث يمكن حسابها تقريبًا "مجانًا" أحيانًا (وهي مهمة في التطبيقات). أعتقد أن هناك طريقين:

(1) استخدم mul!((β₁, Y, β₂), α₁, A, α₂, B, α₃) ولكن عند التحميل الزائد على الطريقة ، يجب أن تقبل الوسيطتان α و β Diagonal . من السهل تحديد مسار المكالمة بحيث يظل بإمكان كود المستخدم النهائي استدعائه عبر القيم العددية. ولكن لكي يعمل هذا بكفاءة ، يجب تطبيق "إصدار O (1)" من Diagonal(fill(λ, n)) https://github.com/JuliaLang/julia/pull/30298#discussion_r239845163 في LinearAlgebra. لاحظ أن تطبيقات α العددية والقطرية لا تختلف كثيرًا ؛ غالبًا ما يتم تبديل α و α.diag[i] . لذلك لا أعتقد أنه يمثل عبئًا كبيرًا على مؤلفي الحزم.

هذا يحل الغموض الذي ذكرته أعلاه لأنه يمكنك الآن استدعاء mul!(Y, α * I, A, B) عندما يكون A مصفوفة مصفوفة و α مصفوفة يجب معاملتها على أنها eltype من A .

(2) ربما المسار أعلاه (1) لا يزال معقدًا جدًا؟ إذا كان الأمر كذلك ، فانتقل إلى muladd! بدلاً من ذلك الآن. إذا أردنا دعم mul!((β₁, Y, β₂), α₁, A, α₂, B, α₃) ، فإن الترحيل إليه مع الحفاظ على التوافق مع الإصدارات السابقة ليس بالأمر الصعب.

في هذه المرحلة ، يجب أن أتساءل عما إذا كان يجب ألا يكون لدينا فقط matmul!(C, A, B, α, β) مقيدًا ومتخصصًا للغاية والذي تم تعريفه فقط للعمل من أجل هذا التوقيع العام:

matmul!(
    C :: VecOrMatT,
    A :: Matrix{T},
    B :: VecOrMatT,
    α :: Union{Bool,T} = true,
    β :: Union{Bool,T} = false,
) where {
    T <: Number,
    VecOrMatT <: VecOrMat{T},
}

أيضًا ، من المدهش حقًا أن تتم كتابة هذا التوقيع وإرساله.

هذا في الأساس اقتراحي (2) ، أليس كذلك؟ (أعتقد أن A :: Matrix{T} لا يعني حرفياً Core.Array{T,2} ؛ وإلا فهو أكثر أو أقل فقط gemm! )

سأكون سعيدًا بذلك كحل مؤقت ، ويمكنني دعمه جزئيًا في الحزم التي أحافظ عليها ("جزئيًا" بسبب مشكلة السمات المعلقة) ، على الرغم من أنه يضيف اسمًا آخر إلى المزيج: mul! ، muladd! والآن matmul! .

... ألم يحن الوقت ليقوم شخص ما بنشر "الفرز يقول ..." ويسميها؟

أيضًا ، من المدهش حقًا أن تتم كتابة هذا التوقيع وإرساله.

ليست حقيقة أنه يمكنك إرسال هذا التوقيع تمامًا إلى مجرد حجة لجعل هذه الطريقة mul! . يمكن أيضًا إهمالها تمامًا في حالة ظهور حل أكثر عمومية.

جعل هذه طريقة mul!

إذا استخدمنا mul!(C, A, B, α, β) فلا توجد طريقة لتعميمه على mul!((β₁, Y, β₂), α₁, A, α₂, B, α₃) وعلى حد سواء دون كسر التوافق. (ربما تكون "ميزة" لأننا متحررين من هذا النقاش إلى الأبد: ابتسم :).

اسمحوا لي أيضًا أن أشير إلى أن نوع العنصر المحيط بـ Number _ و_ الحفاظ على التوافق مع 3-arg mul! (الذي يدعم بالفعل نوع العنصر غير Number ) سيقدم الكثير من الازدواجية.

ليس لدي أي فكرة عما تتوقع أن يفعله mul!((β₁, Y, β₂), α₁, A, α₂, B, α₃) ... لذلك أعتقد أنها ميزة.

صدم. يحزنني أن أضطر إلى استخدام وظائف BLAS في كل مكان للحصول على أداء أفضل في الموقع.

@ StefanKarpinski هل يمكنك

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

أعتقد أن عدم وجود توافق في الآراء يعني أنه ليس الوقت المناسب لدمج هذا في StdLib.

لماذا لا تكون مجرد حزمة MatMul.jl تنفذ أحد الاقتراحات التي يمكن للمستخدمين استخدامها؟ لا أرى سبب أهمية التواجد في StdLib في الممارسة العملية. سأدعم هذا لحسن الحظ في الحزم التي أحافظ عليها.

أنا أفكر فقط في نسخة جوليان لطيفة من الأحجار الكريمة! و gemv! مطابقة ما لدينا في SparseArrays بالفعل. لكل andreasnoack أعلاه:

اعتقدت أننا استقرنا بالفعل على mul!(C, A, B, α, β) مع القيم الافتراضية لـ α ، β . نحن نستخدم هذا الإصدار في

جوليا / stdlib / SparseArrays / src / linalg.jl

الخطوط من 32 إلى 50 في b8ca1a4

...
أعتقد أن بعض الحزم تستخدم هذا النموذج أيضًا ولكني لا أتذكر أيها فوق رأسي.

هذا الاقتراح كان لديه 7 اعجاب ولا ممتاز. لماذا لا نقوم فقط بتنفيذ هذه الوظيفة للمتجهات / المصفوفات الكثيفة؟ سيكون هذا حلاً بسيطًا يغطي حالات الاستخدام الأكثر شيوعًا ، أليس كذلك؟

حسنا. لذلك أعتقد أنه لا يوجد إجماع على ما إذا كان هناك إجماع: sweat_smile:

_I_ اعتقدت أن الجميع [*] أرادوا واجهة برمجة التطبيقات هذه وهي مجرد مسألة اسم الوظيفة والتوقيع. بالمقارنة مع _not_ وجود واجهة برمجة التطبيقات هذه ، أعتقد أن الجميع سعداء بأي من الخيارات (مثل mul!((β₁, Y, β₂), α₁, A, α₂, B, α₃) و muladd!(C, A, B, α, β) و mul!(C, A, B, α, β) ). ما لم يتمكن شخص ما من تقديم حجة مقنعة بأن واجهة برمجة تطبيقات معينة أسوأ بكثير من عدم امتلاكها ، فسأكون سعيدًا بأي شيء يقرره الفرز.

StefanKarpinski ولكن لا تتردد في إزالة علامة triage إذا كنت تعتقد أن المناقشة لم يتم دمجها بشكل كافٍ حتى الآن.

[*] حسنًا ، dlfivefifty ، أعتقد أنك تشك حتى في 3-arg mul! . لكن هذا سيتطلب تغيير واجهة 3-arg mul! من البداية ، لذلك اعتقدت أن هذه طريقة خارج نطاق هذه المناقشة (والتي كنت أفسرها على أنها إضافة إلى شكل من أشكال 5-arg variant). أعتقد أننا بحاجة إلى شيء يعمل "بشكل كافٍ" حتى ينضج LazyArrays.jl.

لماذا لا تكون مجرد حزمة MatMul.jl تنفذ أحد الاقتراحات التي يمكن للمستخدمين استخدامها؟

dlfivefifty أعتقد أن وجوده في LinearAlgebra.jl مهم لأنه وظيفة واجهة (واجهة برمجة تطبيقات قابلة للتحميل بشكل زائد). أيضًا ، نظرًا لأنه تم تطبيق mul!(C::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) في LinearAlgebra.jl ، فلن نتمكن من تحديد mul! من حيث MatMul.muladd! . هناك بالطبع بعض الحلول ، ولكن من الأجمل أن يكون لديك تطبيق مباشر ، خاصة بالنظر إلى أنه "فقط" يتطلب تحديد الاسم والتوقيع.

لماذا لا نقوم فقط بتنفيذ هذه الوظيفة للمتجهات / المصفوفات الكثيفة؟

chriscoey لسوء الحظ ، ليس هذا هو المفضل الوحيد للجميع: https://github.com/JuliaLang/julia/issues/23919#issuecomment -441717678. فيما يلي ملخصي للإيجابيات والسلبيات لهذا الخيار وخيارات أخرى https://github.com/JuliaLang/julia/issues/23919#issuecomment -441865841. (انظر تعليقات الآخرين أيضًا)

من الفرز: هناك خطط طويلة الأجل لوجود واجهات برمجة تطبيقات عامة لتقلص الموتر بما في ذلك دعم المترجم والاختيار إلى BLAS ، ولكن على المدى المتوسط ​​، ما عليك سوى اختيار أي واجهة برمجة تطبيقات تلبي احتياجاتك الفورية. إذا كان يتطابق مع BLAS ، فإن اختيار أسماء BLAS يبدو معقولًا.

Keno ، هل هناك أي معلومات يمكنك مشاركتها حول واجهة برمجة تطبيقات انكماش الموتر العامة ودعم المحول البرمجي؟ قد يكون لدي بعض المعلومات الشيقة لمشاركتها أيضًا ، وإن لم تكن متاحة للعامة (حتى الآن).

لم يتم تنفيذ أي تصميم لواجهة برمجة التطبيقات على أي من ذلك ، فقط إحساس عام بأنه يجب أن نحصل عليه. أنا أدرك أنك كنت تعمل على بعض هذه الأشياء ، لذا سيكون من الجيد أن يكون لديك جلسة تصميم في المنعطف المناسب ، لكنني لا أعتقد أننا وصلنا إلى هناك بعد.

إذا كان يتطابق مع BLAS ، فإن اختيار أسماء BLAS يبدو معقولًا.

هذا مخالف تمامًا لما كنا نفعله حتى الآن بالنسبة لأسماء وظائف الجبر الخطي العامة.

ما هي خطة β == 0 القوي / الضعيف في النسخة العامة المقترحة من BLAS.gemm!(α, A, B, β, C) ؟

إذا خفضنا إلى BLAS للمكالمات ، فسوف يتصرف مثل الصفر القوي ، على الرغم من أن هذا الآن غير متوافق مع lmul! . لا أستطيع التفكير في حل لهذا بصرف النظر عن التراجع إلى generic_muladd! إذا β == 0 .

ما هي الخطة للقوي / الضعيف β == 0

تمت مناقشته لفترة وجيزة فقط حول تعليقي في https://github.com/JuliaLang/julia/issues/23919#issuecomment -430139849 لذلك ربما لم يعالج الفرز هذا السؤال.

Keno على الرغم من عدم وجود أي تصميم لواجهة برمجة التطبيقات حتى الآن ، هل تتصور أن "واجهات برمجة التطبيقات بما في ذلك دعم المترجم والاختيار إلى BLAS" سيتم تعريفها على أنها تحور أو أنها ستكون غير قابلة للتغيير ، مثل الجبر الخطي XLA ، من أجل مساعدة مترجم؟ أي هل تعتقد أن mul! و / أو muladd! سيكونان جزءًا من واجهات برمجة التطبيقات هذه؟

ping @ كينو لسؤال andreasnoack في https://github.com/JuliaLang/julia/issues/23919#issuecomment -475534454

عذرًا ، كان من المفترض أن أعود إلى هذه المشكلة (خاصةً أنني طلبت الفرز) لكن لم أكن أعرف الإجراء التالي الذي سيُعطى القرار من الفرز.

إذا كان يتطابق مع BLAS ، فإن اختيار أسماء BLAS يبدو معقولًا.

كما أشار andreasnoack ، لا يمكننا استخدام (على سبيل المثال) gemm! لأننا نريد دعم مضاعفة متجه المصفوفة وما إلى ذلك ولكن أعتقد أنه يمكننا فقط تجاهل قرار الفرز هذا (الذي يقول فقط "إذا كان يطابق BLAS" ؛ لا).

ما عليك سوى اختيار أي واجهة برمجة تطبيقات تلبي احتياجاتك الفورية.

لذا ، أعتقد أنه يمكننا اتباع هذا الاتجاه. أعتقد أنه يعني نسيان واجهة برمجة التطبيقات المستندة إلى tuple والتي اقترحها StefanKarpinski واختيار "فقط" واحدًا من mul! / muladd! / addmul! .

نعود نوعًا ما إلى المناقشة الأصلية. لكنني أعتقد أنه من الجيد أن يكون لدينا قيود على عدم مناقشة API بعد الآن.

هل لديك فكرة عن كيفية اختيار اسم من mul! / muladd! / addmul! ؟


chriscoey أعتقد أنه من الأفضل مناقشة API المستقبلية في مكان آخر. هذه المشكلة طويلة بالفعل ولن نتمكن من إحراز أي تقدم ما لم نركز على حل متوسط ​​المدى. ماذا عن فتح قضية جديدة (أو موضوع حديث)؟

أقترح جولة تصويت واحدة للموافقة مع مهلة 10 أيام من الآن. التصويت بالموافقة يعني: يصوت الجميع لجميع الخيارات التي يرونها مفضلة على مواصلة المناقشة. يجب على الأشخاص الذين يفضلون الحصول على أقل الأسماء المفضلة لديهم الآن بدلاً من المناقشة المستمرة التصويت لجميع الثلاثة. إذا لم يحظ أي خيار بموافقة واسعة النطاق ، أو إذا فشل مخطط التصويت نفسه في تلبية موافقة واسعة النطاق ، فيجب علينا مواصلة المناقشة. في حالة شبه العلاقات بين الخيارات المعتمدة ، فإن tkf يقرر (امتياز مؤلف العلاقات العامة).

+1: أوافق على نظام التصويت هذا وقد أدليت بصوتي.
-1: أنا لا أتفق مع نظام التصويت هذا. إذا حدد الكثير من الأشخاص أو المهمين جدًا هذا الخيار ، فسيكون التصويت موضع نقاش.

القلب: يُفضل mul! للمناقشة المستمرة.
الصاروخ: يُفضل muladd! للمناقشة المستمرة.
الصيحة: يُفضل addmul! للمناقشة المستمرة.

أقترح مبدئيًا أن 75٪ موافقة و 5 يجب أن يكتمل النصاب القانوني (أي 75٪ من الأشخاص الذين صوتوا على الإطلاق ، بما في ذلك عدم الموافقة على إجراء التصويت بأكمله ، ووافق 5 أشخاص على الأقل على الخيار الفائز ؛ إذا كانت المشاركة منخفضة ، ثم 5/6 أو 6/8 يكتمل النصاب ولكن بالإجماع 4/4 يمكن اعتباره فشلًا).

تجميد الميزة لـ 1.3 حوالي 15 أغسطس: https://discourse.julialang.org/t/release-1-3-branch-date-approaching-aug-15/27233؟u=chriscoey. آمل أن نتمكن من دمجها بحلول ذلك الوقت 😃. شكرا لجميع الذين صوتوا بالفعل!

ما زلنا بحاجة أيضًا إلى تحديد سلوك β == 0 https://github.com/JuliaLang/julia/issues/23919#issuecomment -475420149 وهو متعامد لتحديد الاسم. أيضًا ، يجب حل تعارض الدمج في العلاقات العامة الخاصة بي ويحتاج PR إلى بعض المراجعة حول تفاصيل التنفيذ (على سبيل المثال ، الأسلوب الذي استخدمته هناك للتعامل مع undef s في مصفوفة الوجهة). قد نكتشف مشاكل أخرى أثناء المراجعة. لذلك ، لست متأكدًا مما إذا كان يمكن أن يصل إلى 1.3 ....

رد: β == 0 ، وأعتقد أنandreasnoack الصورة تعليق https://github.com/JuliaLang/julia/issues/23919#issuecomment -430139849 (ملخص بلدي: β == 0 -handling ينبغي أن يكون بلاس -متوافق مع الاستفادة من BLAS قدر الإمكان) أمر منطقي. من الصعب العثور على آراء معارضة بخلاف حجة simonbyrne أدناه مباشرة ("كل تطبيق سيحتاج إلى فرع للتحقق من الصفر"). هل هناك أي حجج أخرى ضد التعامل مع β == 0 مثل BLAS؟

simonbyrne فيما يتعلق https://github.com/JuliaLang/julia/issues/23919#issuecomment -430375349 ، لا أعتقد أن التفرع الصريح يمثل مشكلة كبيرة لأنه في الغالب مجرد خط واحد β != 0 ? rmul!(C, β) : fill!(C, zero(eltype(C))) . أيضًا ، بالنسبة إلى التنفيذ العام جدًا حيث تحتاج إلى التعامل معه ، على سبيل المثال ، C = Matrix{Any}(undef, 2, 2) ، يتطلب التطبيق معالجة "صفرية قوية" صريحة على أي حال (راجع وظيفة المساعد _modify! في العلاقات العامة الخاصة بي https: // github .com / JuliaLang / Julia / pull / 29634 / files # diff-e5541a621163d78812e05b4ec9c33ef4R37). لذلك ، أعتقد أن التعامل مع نظام BLAS هو الخيار الأفضل هنا. ما رأيك؟

هل من الممكن أن يكون لديك أصفار ضعيفة عالية الأداء؟ بمعنى أننا نريد:

julia> A = [NaN 0;
                     1 0]

julia> b = [0.0,0];

julia> 0.0*A*b
2-element Array{Float64,1}:
 NaN  
   0.0

julia> false*A*b
2-element Array{Float64,1}:
 0.0
 0.0

بمعنى ، سنحتاج إلى تحديد الصفوف يدويًا التي من المفترض أن تكون NaN إذا انخفضنا إلى BLAS (الذي يستخدم قويًا 0).

dlfivefifty أعتقد أن BLAS يمكنها التعامل مع NaN بـ A و B ، لكن ليس بـ C ؟

أعتقد أنه لا توجد طريقة للقيام بـ NaN- علم _C = α * A * B + 0 * C_ بكفاءة باستخدام BLAS.gemm! إلخ. [1] ومن هنا تأتي حجة andreasnoack .

[1] تحتاج إلى حفظ isnan.(C) مكان ما و "تلوث" C بعد ذلك

chethega لقد مر أكثر من 10 أيام منذ التصويت

chriscoey أنت محق ، التصويت مغلق.

أنا سيء للغاية في github للحصول على قائمة كاملة بالأشخاص الذين صوتوا (سيكون ذلك مطلوبًا لحساب عدد الأشخاص الذين أدلوا بأي أصوات على الإطلاق). ومع ذلك ، عندما أنظر إلى الأرقام ، يبدو واضحًا تمامًا أن mul! لديه دعم ساحق (ربما يدير 75٪ من نصاب الموافقة) ، وأن المنافس الثاني muladd! أقل بكثير من 50٪.

لم يكن هناك اعتراض واحد على خطة التصويت. أدعو التصويت ، لقد فاز mul! ، وتم تحديد الاسم. tkf يمكن أن تستمر في جعلها تطير :)

chethega شكرًا ، لقد كان مخططًا

راجع للشغل ، لا يمكنني إجراء تغيير العنوان على الفور (ولكن ربما في غضون بضعة أسابيع) ، لذا إذا أراد شخص ما إجراء إعادة الأساسي أو إعادة التنفيذ ، فالرجاء عدم الانتظار.

لسوء الحظ ، لم يكن لدينا تصويت على دلالات NaN. تجميد الميزات الأسبوع المقبل ، وليس لدينا الوقت الكافي لإجراء تصويت ذي مغزى.

أقترح أن يكون لدينا استفتاء غير ملزم نجمع لمحة سريعة عن الحالة المزاجية في الموضوع.

أرى الخيارات التالية:

  1. استمر في المناقشة ، آمل أن يتم التوصل إلى توافق في الآراء بطريقة ما قبل الموعد النهائي ، أو يمنحنا الأشخاص الأساسيون تمديدًا ، أو شيء من هذا القبيل. : tada: (عدل للتوضيح: هذا هو الخيار الافتراضي ، أي ما يحدث إذا لم نتمكن من التوصل إلى إجماع على خيار مختلف. والنتيجة الأكثر احتمالية هي أن 5-arg mul! يتأخر حتى 1.4.)
  2. ادمج الميزة الجديدة ، مع سلوك NaN غير المحدد كمسند. بمجرد أن نتوصل إلى إجماع ، نقوم بتحديث الكود و / أو المستندات للحصول على سلوك NaN المحدد (الأصفار القوية مقابل الأصفار الضعيفة). قد ينتهي الأمر بدعم سلوك NaN غير المحدد من قبل التنفيذ إلى أجل غير مسمى ، لكن هذا ليس للتصويت اليوم. (نفذ كل ما هو أسرع ؛ يحتاج المستخدمون المهتمون إلى استدعاء طرق مختلفة). :رضى وقبول:
  3. الجوهرة تعني الجوهرة! الدمج لـ 1.3 مع الالتزام الموثق بالأصفار القوية. :قلب:
  4. NaN يعني NaN ! الدمج لـ 1.3 مع الالتزام الموثق بالأصفار الضعيفة. : عيون:
  5. افعل شيئًا ، أي شيء ، قبل أن تصل إلى الجرف 1.3. :صاروخ:
  6. رفض الاستطلاع. :استهجن:
  7. اكتب في
  8. انخفاض مؤشر التداول المقترح: ترتيب بديل بديل. حاول الاندماج بسرعة ، واجعل الانحراف الصفري الضعيف / القوي خطأً لـ 1.3-alpha ، حتى نتمكن من التوصل إلى قرار مدروس أكثر لاحقًا. وهذا يعني أننا ندمج مع !(alpha === false) && iszero(alpha) && !all(isfinite, C) && throw(ArgumentError()) ، ووثقنا أنه من المحتمل أن يتم إيقاف التحقق من الخطأ هذا لصالح شيء آخر. :مشوش:

لا تتردد في تحديد خيارات متعددة ، ربما تكون متناقضة ، و tkf / triage لا تتردد في تجاهل الاستطلاع.

تحرير: حاليًا فقط: tada: (الصبر) و: صاروخ: (نفاد الصبر) متناقضان ، لكن كلاهما متوافق مع الآخرين. كما هو موضح أسفل مؤشر الترابط ، من المأمول أن يقوم الفرز بحساب نتيجة الاستطلاع في تاريخ غير محدد بين 14 الأربعاء والخميس 15 ، وأخذها في الاعتبار بطريقة غير محددة. يُقصد بهذا مرة أخرى "تصويت الموافقة" ، أي تحديد جميع الخيارات التي تريدها ، وليس الخيار المفضل لديك فقط ؛ ومن المعلوم أن: صاروخ: لا يرفض: إبهام :،: قلب: ،: عيون: و: مرتبك:. أعتذر أن هذا الاستطلاع متسرع أكثر من السابق.

كنت سأصوت للصفر القوي (: heart :) إذا كان "دمج لـ 1.x" بدلاً من "دمج لـ 1.3". ألن تكون الخيارات منطقية إذا كانت كل "دمج لـ 1.3" هي "دمج 1.x"؟

شكرا جزيلا. tkf أنا في موقف أحتاج حقًا إلى مول جديد! في أسرع وقت ممكن دون الاهتمام كثيرًا بقرار NaN (طالما لم يتم المساس بالأداء).

هل قمت بفحص LazyArrays.jl؟ لمعلوماتك ، إنه يحتوي على دعم ضرب مصفوفة مدمج لطيف حقًا. يمكنك أيضًا استخدام BLAS.gemm! إلخ بأمان نظرًا لأنها طرق عامة https://docs.julialang.org/en/latest/stdlib/LinearAlgebra/#LinearAlgebra.BLAS.gemm!

أنا فعلا بحاجة حقا مول عام! نظرًا لأننا نستخدم مجموعة متنوعة من المصفوفات القديمة الكثيفة المنظمة والمتفرقة والبسيطة ، لتمثيل مشكلات التحسين المختلفة بكفاءة أكبر. أنا هنا من أجل العموم والسرعة.

أنا أرى. وتذكرت للتو أننا ناقشنا الأشياء في LazyArrays.jl لذا بالطبع كنت تعرف ذلك بالفعل ...

فيما يتعلق بـ "ASAP" ، فإن دورة إصدار Julia لمدة أربعة أشهر ، على الأقل كتصميم ، لتجنب "اندماج الاندفاع" قبل تجميد الميزة مباشرة. أعلم أنه ليس من العدل أن أقول هذا لأنني حاولت نفس الشيء من قبل ... لكنني أعتقد أن هناك من يحتاج إلى ذكر هذا كتذكير. الجانب المشرق هو أن جوليا سهلة البناء للغاية. يمكنك البدء في استخدامه مباشرة بعد دمجه حتى الإصدار التالي.

تحرير: الإفراج -> دمج

شكر. أجد المواعيد النهائية بمثابة محفزات مفيدة ، وأود تجنب ترك هذا الأمر قديمًا مرة أخرى. لذا أقترح أن نحاول استخدام الموعد النهائي كهدف.

إنه لأمر رائع أنك تقوم بحقن الطاقة بنشاط في هذا الخيط!

أنا فعلا بحاجة حقا مول عام! نظرًا لأننا نستخدم مجموعة متنوعة من المصفوفات القديمة الكثيفة المنظمة والمتفرقة والبسيطة ، لتمثيل مشكلات التحسين المختلفة بكفاءة أكبر. أنا هنا من أجل العموم والسرعة.

لن تعمل الوسيطة الخمسة mul! بشكل جيد عندما يكون لديك العديد من الأنواع المختلفة: ستحتاج إلى العديد من التجاوزات المجمعة لتجنب الغموض. هذا هو أحد الدوافع وراء نظام LazyArrays.jl MemoryLayout . يتم استخدامه للمصفوفات "المنظمة والمتفرقة" على وجه التحديد لهذا السبب في BandedMatrices.jl و BlockBandedMatrices.jl. (هنا يتم إرسال حتى العروض الفرعية لمصفوفات النطاقات إلى إجراءات BLAS النطاقات.)

شكرًا ، سأحاول LazyArrays مرة أخرى.

نظرًا لأن 5-arg mul يبدو أنه يُعتبر عمومًا بمثابة فجوة مؤقتة (حتى يمكن استخدام بعض الحلول مثل LazyArrays في 2.0) ، أعتقد أنه يمكننا أن نهدف إلى دمجها دون أن تكون بالضرورة الحل المثالي أو المثالي على المدى الطويل.

chethega متى الأرقام للتصويت الجديد غير الملزم؟

tkf بالتأكيد ، أنت محق في أن الأصفار القوية / الضعيفة / undef تبدو منطقية لـ 1.x أيضًا.

ومع ذلك ، أعتقد أن هناك عددًا غير قليل من الأشخاص الذين يفضلون الحصول على 1.3 mul! الآن بدلاً من الانتظار حتى 1.4 للحصول على 5-arg mul! . إذا لم يكن هناك موعد نهائي ، فسأنتظر أكثر وأستغرق بعض الوقت للتفكير في كيفية إجراء اقتراع مناسب (10 أيام على الأقل للتصويت). والأهم من ذلك ، أنه لا يمكننا الحصول على تصويت ذي مغزى دون تقديم وقياس التطبيقات المتنافسة أولاً على سرعة وأناقة الأصفار الضعيفة / القوية. أنا شخصياً أظن أنه يمكن تكوين الأصفار الضعيفة بنفس سرعة الأصفار القوية ، عن طريق التحقق أولاً من iszero(alpha) ، ثم مسح المصفوفة لقيم !isfinite ، وبعد ذلك فقط باستخدام مسار بطيء مع تخصيص إضافي ؛ لكني أفضل دلالات الصفر القوية على أي حال.

chethega متى الأرقام للتصويت الجديد غير الملزم؟

يجب أن يتخذ الفرز قرارًا (تأخير / قوي / ضعيف / مساند) هذا الأسبوع بالنسبة لـ 1.3 ألفا. أعتقد أن الخميس 15 أو الأربعاء 14 خياران معقولان لفرز العد ، وأخذها في الاعتبار. ربما لن أتمكن من الانضمام يوم الخميس ، لذلك سيتعين على شخص آخر الاعتماد.

من الناحية الواقعية ، لا بأس من أن تكون متحفظًا هنا ، وتفوتك الموعد النهائي ، وتواصل المناقشة وانتظر 1.4.

من ناحية أخرى ، ربما نكون قد توصلنا بالفعل إلى توافق في الآراء دون أن نلاحظ ذلك: قدم

لماذا لا نخطئ فقط في الوقت الحالي:

β == 0.0 && any(isnan,C) && throw(ArgumentError("use β = false"))

لماذا لا نلقي خطأ الآن

لقد أضفت هذا الخيار إلى الاستطلاع. فكرة حل وسط رائعة!

فقط لتعيين التوقعات: يتم تجميد الميزة لـ 1.3 في ثلاثة أيام ، لذلك لا توجد طريقة أساسية يمكن من خلالها تحقيق ذلك في الوقت المناسب. نحن صارمون جدًا بشأن تجميد الميزات والتفرع نظرًا لأنه الجزء الوحيد من دورة الإصدار الذي يمكننا حقًا التحكم في توقيته.

تم الانتهاء من العمل بالفعل في https://github.com/JuliaLang/julia/pull/29634 . يحتاج فقط إلى التعديل وإعادة التأسيس.

tkf لـ # 29634 ، هل يمكنك سرد العمل المتبقي (بما في ذلك إعادة تسمية ومعالجة الأصفار وفقًا للتصويت)؟ أعلم أنك مشغول ، لذا ربما يمكننا إيجاد طريقة لتقسيم أي مهام متبقية حتى لا يقع العبء عليك مرة أخرى.

TODOs التي يمكنني التفكير فيها عن أجهزة الصراف الآلي هي:

  • تغيير العنوان
  • إعادة تسمية addmul! -> mul!

    • وتعديل الكود بافتراض أن واجهة برمجة التطبيقات الجديدة لن تسمى mul! (على سبيل المثال ، <strong i="15">@deprecate</strong> mul!(C, A, B, α, β) addmul!(C, A, B, α, β) )

  • الحصول على موافقة من المطورين الأساسيين حول استراتيجية التنفيذ MulAddMul وما إلى ذلك ؛ انظر https://github.com/JuliaLang/julia/pull/29634#issuecomment -440510551. andreasnoack ، هل لديك فرصة للنظر في ذلك؟
  • من الناحية المثالية ، قم بإضافة الاختبارات باستخدام Quaternion ؛ انظر https://github.com/JuliaLang/julia/pull/29634#issuecomment -443379914

يطبق My PR دلالات BLAS الخاصة بمعالجة β = 0 . لذلك يجب أيضًا تنفيذ معالجة أخرى ، مثل إلقاء خطأ.

يطبق My PR دلالات BLAS للمعالجة β = 0 .

آسف ، ذاكرتي كانت قديمة. لم يكن تطبيقي متسقًا وينتشر NaN في بعض الأحيان. لذا فإن TODO الإضافي هو جعل سلوك β = 0.0 ثابتًا.

النوع MulAddMul سيكون فقط للاستخدام الداخلي ، أليس كذلك؟

نعم ، إنها تفاصيل داخلية بالكامل. كانت مخاوفي (1) قد يكون هناك الكثير من التخصصات (بيتا = 0 وما إلى ذلك مشفرة في معلمة النوع) و (2) تقلل من قابلية قراءة كود المصدر.

هذه مخاوف صحيحة. نحن بالفعل ننتج عددًا كبيرًا من التخصصات في كود الجبر الخطي ، لذا من الجيد التفكير فيما إذا كنا بحاجة حقًا إلى التخصص هنا. كان تفكيري عمومًا هو أنه يجب علينا تحسين المصفوفات الصغيرة نظرًا لأنها ليست مجانية (كما قلت ، فهي تعقد شفرة المصدر ويمكن أن تزيد من أوقات التجميع) ويكون الأشخاص أفضل حالًا باستخدام StaticArrays لمضاعفات المصفوفة الصغيرة. ومن ثم ، فإنني أميل إلى التحقق من القيم فقط في وقت التشغيل ، لكن يمكننا دائمًا تعديل هذا لاحقًا إذا غيرنا رأينا ، لذا لا ينبغي أن ندع هذا يتسبب في أي تأخير.

تحتوي FYI soft zeros على تطبيقات بسيطة:

if iszero(β) && β !== false && !iszero(α)
   lmul!(zero(T),y) # this handles soft zeros correctly
   BLAS.gemv!(α, A, x, one(T), y) # preserves soft zeros
elseif iszero(α) && iszero(β)
   BLAS.gemv!(one(T), A, x, one(T), y) # puts NaNs in the correct place
   lmul!(zero(T), y) # everything not NaN should be zero
elseif iszero(α) && !iszero(β)
   BLAS.gemv!(one(T), A, x, β, y) # puts NaNs in the correct place
   BLAS.gemv!(-one(T), A, x, one(T), y) # subtracts out non-NaN changes
end

andreasnoack معذرة ، لقد نسيت أننا بحاجة فعلاً إلى التخصص لتحسين الحلقة الداخلية لبعض المصفوفات المهيكلة مثل mul!(C, A::BiTriSym, B, α, β) https://github.com/JuliaLang/julia/pull/29634#issuecomment -440510551. يمكن إزالة بعض التخصصات ولكن هذا في الواقع يتطلب المزيد من العمل (لذا فإن التأخير).

ومن ثم ، فإنني أميل إلى التحقق من القيم فقط في وقت التشغيل ، لكن يمكننا دائمًا تعديل هذا لاحقًا إذا غيرنا رأينا ، لذا لا ينبغي أن ندع هذا يتسبب في أي تأخير.

عظيم!

تم الإصلاح بواسطة https://github.com/JuliaLang/julia/pull/29634

andreasnoack شكرًا جزيلاً على المراجعة ودمج هذا في الوقت المناسب!

الآن بعد أن تم دمجه لـ 1.3 بدأ يجعلني أشعر بالتوتر الشديد بشأن التنفيذ: ابتسم :. إنني أقدر ما إذا كان بإمكان الأشخاص هنا اختبار كود الجبر الخطي بشكل أكثر شمولاً عند ظهور 1.3-rc!

لا داعي للقلق ، سيكون هناك متسع من الوقت لـ 1.3 RCs + PkgEvals للتخلص من الأخطاء.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات