دلالات العمليات

يوضِّح ما يلي دلالات العمليات المحدّدة في واجهة XlaBuilder. يتم عادةً ربط هذه العمليات بشكلٍ مباشر بالعمليات المحدّدة في واجهة RPC في xla_data.proto.

ملاحظة حول التسمية: نوع البيانات العام الذي تتعامل معه XLA هو آرامٍ بأبعاد N تحتوي على عناصر من نوع موحّد (مثل 32 بت عائمة). في جميع المستندات، يُستخدَم صفيف للإشارة إلى صفيف بأبعاد عشوائية. لتسهيل الأمر، تحمل الحالات الخاصة أسماء أكثر تحديدًا وشيوعًا، على سبيل المثال، المتجه هو صفيف أحادي الأبعاد و المصفوفة هي صفيف ثنائي الأبعاد.

AfterAll

يمكنك الاطّلاع أيضًا على XlaBuilder::AfterAll.

يأخذ AfterAll عددًا متغيرًا من الرموز المميّزة وينشئ رمزًا مميّزًا واحدًا. الرموز المميّزة هي أنواع أساسية يمكن ربطها بين العمليات التي تؤدي إلى تأثيرات جانبية لفرض الترتيب. يمكن استخدام AfterAll كعملية دمج للرموز لترتيب عملية بعد مجموعة من العمليات.

AfterAll(operands)

الوسيطات النوع الدلالات
operands XlaOp عدد متغيّر من الرموز المميّزة

AllGather

يمكنك الاطّلاع أيضًا على XlaBuilder::AllGather.

تُجري عملية الربط على مستوى النُسخ المكرّرة.

AllGather(operand, all_gather_dim, shard_count, replica_group_ids, channel_id)

الوسيطات النوع الدلالات
operand XlaOp صفيف لتسلسل العناصر في كل النسخ
all_gather_dim int64 سمة الربط
replica_groups متّجه المتّجهات int64 المجموعات التي يتم بينها تسلسل
channel_id اختياري int64 معرّف قناة اختياري للتواصل بين الوحدات
  • replica_groups هي قائمة بمجموعات النُسخ المكرّرة التي يتم بينها تنفيذ التسلسل (يمكن استرداد معرّف النسخة المكرّرة الحالية باستخدام ReplicaId). يحدّد ترتيب النُسخ المكرّرة في كل مجموعة الترتيب الذي يتم فيه العثور على مدخلاتها في النتيجة. يجب أن يكون replica_groups فارغًا (وفي هذه الحالة تنتمي جميع النُسخ المكرّرة إلى مجموعة واحدة، مرتّبة من 0 إلى N - 1)، أو أن يحتوي على عدد العناصر نفسه المُدرَج في عدد النُسخ المكرّرة. على سبيل المثال، يُجري replica_groups = {0, 2}, {1, 3} دمجًا بين النُسخ المكرّرة 0 و2 و1 و3.
  • shard_count هو حجم كل مجموعة نُسخ. نحتاج إلى ذلك في الحالات التي تكون فيها قيمة الحقل replica_groups فارغة.
  • يتم استخدام channel_id للتواصل بين الوحدات: لا يمكن إلا all-gather للعمليات التي تستخدم channel_id نفسه التواصل مع بعضها.

شكل الإخراج هو شكل الإدخال مع all_gather_dim الذي تم shard_count مضاعفته. على سبيل المثال، إذا كانت هناك نسختان طبق الأصل وكان الم Operand يملك القيمة [1.0, 2.5] و[3.0, 5.25] على التوالي في كلتا النُسختَين، ستكون قيمة الإخراج من هذا الإجراء حيث يكون all_gather_dim هو 0 هي [1.0, 2.5, 3.0, 5.25] في كلتا النُسختَين.

AllReduce

يمكنك الاطّلاع أيضًا على XlaBuilder::AllReduce.

تُجري عملية حسابية مخصّصة على النُسخ المكرّرة.

AllReduce(operand, computation, replica_group_ids, channel_id)

الوسيطات النوع الدلالات
operand XlaOp صفيف أو مجموعة غير فارغة من صفائف لتقليلها في النُسخ المكرّرة
computation XlaComputation احتساب التخفيض
replica_groups متّجه المتّجهات int64 المجموعات التي يتم إجراء التخفيضات بينها
channel_id اختياري int64 معرّف قناة اختياري للتواصل بين الوحدات
  • عندما تكون operand مصفوفة من الصفائف، يتم تنفيذ دالة all-reduce على كل عنصر من المصفوفة.
  • replica_groups هي قائمة بمجموعات النُسخ المكرّرة التي يتم التخفيض بينها (يمكن استرداد معرّف النسخة المكرّرة الحالية باستخدام ReplicaId). يجب أن تكون replica_groups فارغة (في هذه الحالة تنتمي كل النُسخ المكرّرة إلى مجموعة واحدة)، أو أن تحتوي على العدد نفسه من العناصر مثل عدد النُسخ المكرّرة. على سبيل المثال، يُجري replica_groups = {0, 2}, {1, 3} عملية تقليل بين النُسخ المكرّرة 0 و2 و1 و 3.
  • يتم استخدام channel_id للتواصل بين الوحدات: لا يمكن إلا all-reduce للعمليات التي تستخدم channel_id نفسه التواصل مع بعضها.

يكون شكل الإخراج هو نفسه شكل الإدخال. على سبيل المثال، إذا كانت هناك نسختان مكرّرة وكان المعامل يملك القيمة [1.0, 2.5] و[3.0, 5.25] على التوالي في النسختَين المكرّرتين، ستكون قيمة الإخراج من عملية التشغيل هذه وحساب المجموع هي [4.0, 7.75] في كلتا النسختَين المكرّرتين. إذا كان الإدخال هو مجموعة، يكون الناتج هو مجموعة أيضًا.

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

AllToAll

يمكنك الاطّلاع أيضًا على XlaBuilder::AllToAll.

AllToAll هي عملية جماعية تُرسِل البيانات من جميع النوى إلى جميع النوى. وتتضمّن مرحلتين:

  1. مرحلة الانتشار في كل نواة، يتم تقسيم المعامل إلى split_count عدد من الكتل على طول split_dimensions، ويتم توزيع الكتل على جميع النوى، على سبيل المثال، يتم إرسال الكتلة رقم i إلى النواة رقم i.
  2. مرحلة الالتقاط يربط كلّ نواة الكتل المستلَمة على طول concat_dimension.

يمكن ضبط النوى المشارِكة من خلال:

  • replica_groups: تحتوي كل مجموعة نُسخ مطابقة على قائمة بأرقام تعريف النُسخ المطابقة المشارِكة في عملية الحساب (يمكن retrieving retrieving رقم تعريف النسخة المطابقة الحالية باستخدام ReplicaId). سيتم تطبيق AllToAll داخل المجموعات الفرعية بالترتيب المحدّد. على سبيل المثال، تعني replica_groups = { {1,2,3}, {4,5,0} } أنّه سيتم تطبيق AllToAll ضمن النُسخ المكرّرة {1, 2, 3}، وفي مرحلة التجميع، سيتم تسلسل الوحدات المستلَمة بالترتيب نفسه 1 و2 و3. بعد ذلك، سيتم تطبيق AllToAll آخر ضمن النُسخ 4 و5 و0، وسيكون ترتيب التسلسل هو 4 و5 و0 أيضًا. إذا كانت replica_groups فارغة، تنتمي جميع النُسخ المطابقة إلى مجموعة واحدة، وذلك بترتيب التسلسل الذي تظهر به.

المتطلبات الأساسية:

  • حجم سمة الم Operand في split_dimension قابل للقسمة على split_count.
  • شكل الم Operand ليس صفيفًا.

AllToAll(operand, split_dimension, concat_dimension, split_count, replica_groups)

الوسيطات النوع الدلالات
operand XlaOp مصفوفة إدخال من n سمة
split_dimension int64 قيمة في الفاصل [0, n) تُحدِّد السمة التي يتم تقسيم الم Operand على أساسها
concat_dimension int64 قيمة في الفاصل [0, n) تُحدِّد السمة التي يتم تجميع المربّعات المُقسّمة بطولها
split_count int64 عدد النوى التي تشارك في هذه العملية. إذا كان الحقل replica_groups فارغًا، يجب أن يكون هذا العدد هو عدد النُسخ، وإلا يجب أن يكون هذا العدد مساويًا لعدد النُسخ في كل مجموعة.
replica_groups ReplicaGroup متّجه تحتوي كل مجموعة على قائمة بأرقام تعريف النُسخ المكرّرة.

في ما يلي مثال على Alltoall.

XlaBuilder b("alltoall");
auto x = Parameter(&b, 0, ShapeUtil::MakeShape(F32, {4, 16}), "x");
AllToAll(x, /*split_dimension=*/1, /*concat_dimension=*/0, /*split_count=*/4);

في هذا المثال، هناك 4 نوى تشارك في Alltoall. في كل نواة، يتم تقسيم المُشغِّل إلى 4 أجزاء على طول السمة 1، لذا يكون لكل جزء الشكل f32[4,4]. يتم توزيع الأجزاء الأربعة على جميع النوى. بعد ذلك، يربط كلّ نواة الأجزاء المستلَمة على طول السمة 0، بترتيب النواة 0-4. وبالتالي، يكون شكل الإخراج على كل نواة هو f32[16,4].

BatchNormGrad

اطّلِع أيضًا على XlaBuilder::BatchNormGrad والبحث الأصلي عن تقنية تسويّة اللقطات للحصول على وصف مفصّل للخوارزمية.

تُحسِب هذه الدالة مشتقات معيار الدالة.

BatchNormGrad(operand, scale, mean, variance, grad_output, epsilon, feature_index)

الوسيطات النوع الدلالات
operand XlaOp مصفوفة ثنائية الأبعاد المطلوب توحيدها (x)
scale XlaOp صفيف أحادي الأبعاد (\(\gamma\))
mean XlaOp صفيف أحادي الأبعاد (\(\mu\))
variance XlaOp صفيف أحادي الأبعاد (\(\sigma^2\))
grad_output XlaOp تم تمرير التدرجات إلى BatchNormTraining (\(\nabla y\))
epsilon float قيمة Epsilon (\(\epsilon\))
feature_index int64 فهرس سمة الميزة في operand

لكلّ سمة في سمة العنصر (feature_index هو فهرس سمة العنصر في operand)، تحتسِب العملية التدرّجات المتعلّقةoperand وoffset وscale في جميع السمات الأخرى. يجب أن يكون feature_index فهرسًا صالحًا لسمة العنصر في operand.

يتم تعريف التدرجات الثلاثة باستخدام الصيغ التالية (على افتراض أنّه يتم استخدام صفيف من 4 أبعاد على النحو operand مع فهرس سمة السمة l وحجم الدفعة m والأحجام المكانية w وh):

\[ \begin{split} c_l&= \frac{1}{mwh}\sum_{i=1}^m\sum_{j=1}^w\sum_{k=1}^h \left( \nabla y_{ijkl} \frac{x_{ijkl} - \mu_l}{\sigma^2_l+\epsilon} \right) \\\\ d_l&= \frac{1}{mwh}\sum_{i=1}^m\sum_{j=1}^w\sum_{k=1}^h \nabla y_{ijkl} \\\\ \nabla x_{ijkl} &= \frac{\gamma_{l} }{\sqrt{\sigma^2_{l}+\epsilon} } \left( \nabla y_{ijkl} - d_l - c_l (x_{ijkl} - \mu_{l}) \right) \\\\ \nabla \gamma_l &= \sum_{i=1}^m\sum_{j=1}^w\sum_{k=1}^h \left( \nabla y_{ijkl} \frac{x_{ijkl} - \mu_l}{\sqrt{\sigma^2_{l}+\epsilon} } \right) \\\\\ \nabla \beta_l &= \sum_{i=1}^m\sum_{j=1}^w\sum_{k=1}^h \nabla y_{ijkl} \end{split} \]

تمثل المدخلات mean وvariance قيم اللحظات على مستوى السمتَين المجمّعة والمكانية.

نوع الإخراج هو مجموعة من ثلاثة أسماء معرِّفة:

النواتج النوع الدلالات
grad_operand XlaOp التدرّج بالنسبة إلى الإدخال operand ($\nabla x$)
grad_scale XlaOp التدرّج بالنسبة إلى الإدخال scale ($\nabla \gamma$)
grad_offset XlaOp التدرّج بالنسبة إلى المدخل offset($\nabla \beta$)

BatchNormInference

اطّلِع أيضًا على XlaBuilder::BatchNormInference والبحث الأصلي عن تقنية تسويّة اللقطات للحصول على وصف مفصّل للخوارزمية.

تسويف صفيف على مستوى السمات المكانية والدفعة

BatchNormInference(operand, scale, offset, mean, variance, epsilon, feature_index)

الوسيطات النوع الدلالات
operand XlaOp صفيف من n سمة ليتم تسويته
scale XlaOp صفيف أحادي الأبعاد
offset XlaOp صفيف أحادي الأبعاد
mean XlaOp صفيف أحادي الأبعاد
variance XlaOp صفيف أحادي الأبعاد
epsilon float قيمة Epsilon
feature_index int64 فهرس سمة الميزة في operand

لكلّ ميزة في سمة الميزة (feature_index هو فهرس سمة الميزة في operand)، تحتسِب العملية المتوسط والتباين على مستوى جميع السمات الأخرى، وتستخدِم المتوسط والتباين لتسويه كلّ عنصر في operand. يجب أن يكون feature_index فهرسًا صالحًا لسمة السمة في operand.

BatchNormInference مكافئة لاستدعاء BatchNormTraining بدون حساب mean وvariance لكل دفعة. ويستخدم الإدخال mean و variance بدلاً من ذلك كقيم مقدَّرة. يهدف هذا الإجراء إلى تقليل وقت الاستجابة في الاستنتاج، ومن هنا جاء اسم BatchNormInference.

الناتج هو صفيف منتظم ذي n سمة بالشكل نفسه للصفيف المُدخل operand.

BatchNormTraining

يمكنك أيضًا الاطّلاع على XlaBuilder::BatchNormTraining وthe original batch normalization paper للاطّلاع على وصف تفصيلي للخوارزمية.

تسويف صفيف على مستوى السمات المكانية والدفعة

BatchNormTraining(operand, scale, offset, epsilon, feature_index)

الوسيطات النوع الدلالات
operand XlaOp مصفوفة ثنائية الأبعاد المطلوب توحيدها (x)
scale XlaOp صفيف أحادي الأبعاد (\(\gamma\))
offset XlaOp صفيف أحادي الأبعاد (\(\beta\))
epsilon float قيمة Epsilon (\(\epsilon\))
feature_index int64 فهرس سمة الميزة في operand

لكلّ ميزة في سمة الميزة (feature_index هو فهرس سمة الميزة في operand)، تحتسِب العملية المتوسط والتباين على مستوى جميع السمات الأخرى، وتستخدِم المتوسط والتباين لتسويه كلّ عنصر في operand. يجب أن يكون feature_index فهرسًا صالحًا لسمة السمة في operand.

تُنفَّذ الخوارزمية على النحو التالي لكل دفعة في operand \(x\) التي تحتوي على m عناصر مع w وh كحجم للأبعاد المكانية (على افتراض أنّ operand هي صفيف من 4 أبعاد):

  • تُحتسب قيمة متوسط المجموعة \(\mu_l\) لكلّ سمة l في سمة السمة: \(\mu_l=\frac{1}{mwh}\sum_{i=1}^m\sum_{j=1}^w\sum_{k=1}^h x_{ijkl}\)

  • احتساب التباين في المجموعة \(\sigma^2_l\): $\sigma^2l=\frac{1}{mwh}\sum{i=1}^m\sum{j=1}^w\sum{k=1}^h (x_{ijkl} - \mu_l)^2$

  • تسويتها وتحويلها إلى مقاييس وتغييرها: \(y_{ijkl}=\frac{\gamma_l(x_{ijkl}-\mu_l)}{\sqrt[2]{\sigma^2_l+\epsilon} }+\beta_l\)

تتم إضافة قيمة epsilon، وهي عادةً رقم صغير، لتجنُّب أخطاء القسمة على صفر.

نوع الإخراج هو مجموعة من ثلاثة XlaOp:

النواتج النوع الدلالات
output XlaOp مصفوفة من n سمة بالشكل نفسه للإدخال operand (y)
batch_mean XlaOp صفيف أحادي الأبعاد (\(\mu\))
batch_var XlaOp صفيف أحادي الأبعاد (\(\sigma^2\))

batch_mean وbatch_var هما لحظتان يتم احتسابهما على مستوى السمتَين "الدفعة" و "المسافة" باستخدام الصيغ أعلاه.

BitcastConvertType

يمكنك الاطّلاع أيضًا على XlaBuilder::BitcastConvertType.

على غرار tf.bitcast في TensorFlow، تُنفِّذ عملية تحويل ثنائي برمجيًا على مستوى العنصر من شكل بيانات إلى شكل مستهدَف. يجب أن يكون حجم الإدخال والإخراج متطابقًا: على سبيل المثال، تصبح عناصر s32 عناصر f32 من خلال إجراء تحويل الوحدات، وسيصبح عنصر s32 واحدًا أربعة عناصر s8. يتم تنفيذ Bitcast كتحويل أدنى مستوى، لذا فإنّ الأجهزة التي تستخدم طرقًا مختلفة لتمثيل الأرقام الكسورية ستقدّم بدورها نتائج مختلفة.

BitcastConvertType(operand, new_element_type)

الوسيطات النوع الدلالات
operand XlaOp صفيف من النوع T مع سمات D
new_element_type PrimitiveType النوع U

يجب أن تتطابق أبعاد الم Operand والشكل المستهدَف، باستثناء السمة الأخيرة التي ستتغيّر حسب نسبة الحجم الأساسي قبل وبعد التحويل.

يجب ألا تكون أنواع عناصر المصدر والوجهة مجموعات ثنائية.

تحويل Bitcast إلى نوع بدائي بعرض مختلف

BitcastConvert تتيح تعليمات HLO الحالة التي لا يكون فيها حجم نوع T' العنصر الناتج مساويًا لحجم عنصر الإدخال T. بما أنّ العملية الكاملة هي عملية بث بتات من الناحية النظرية ولا تغيّر وحدات البت الأساسية، يجب تغيير شكل عنصر الإخراج. بالنسبة إلى B = sizeof(T), B' = sizeof(T')، هناك حالتان محتملتان.

أولاً، عندما يكون B > B'، يحصل شكل الإخراج على أصغر بعد جديد بحجم B/B'. على سبيل المثال:

  f16[10,2]{1,0} %output = f16[10,2]{1,0} bitcast-convert(f32[10]{0} %input)

تظلّ القاعدة كما هي بالنسبة إلى القيم الكلية الفعّالة:

  f16[2]{0} %output = f16[2]{0} bitcast-convert(f32[] %input)

بدلاً من ذلك، بالنسبة إلى B' > B، يتطلب الإجراء أن تكون السمة المنطقية الأخيرة لشكل الإدخال مساوية لـ B'/B، ويتم حذف هذه السمة أثناء التحويل:

  f32[10]{0} %output = f32[10]{0} bitcast-convert(f16[10,2]{1,0} %input)

يُرجى العلم أنّ عمليات التحويل بين عروض البت المختلفة لا تتم على مستوى العنصر.

البث

يمكنك الاطّلاع أيضًا على XlaBuilder::Broadcast.

تضيف السمات إلى صفيف من خلال تكرار البيانات في الصفيف.

Broadcast(operand, broadcast_sizes)

الوسيطات النوع الدلالات
operand XlaOp الصفيف المطلوب تكراره
broadcast_sizes ArraySlice<int64> أحجام السمات الجديدة

يتم إدراج السمات الجديدة على يمين العنصر، أي إذا كان broadcast_sizes يحتوي على قيم {a0, ..., aN} وكان شكل المعامل يحتوي على سمات {b0, ..., bM}، عندئذٍ يحتوي شكل الإخراج على سمات {a0, ..., aN, b0, ..., bM}.

فهرس السمات الجديدة في نُسخ من الم Operand، أي

output[i0, ..., iN, j0, ..., jM] = operand[j0, ..., jM]

على سبيل المثال، إذا كان operand عددًا قياسيًا f32 بقيمة 2.0f، وكان broadcast_sizes هو {2, 3}، ستكون النتيجة صفيفًا بالتنسيق f32[2, 3] وستكون كل القيم في النتيجة هي 2.0f.

BroadcastInDim

يمكنك الاطّلاع أيضًا على XlaBuilder::BroadcastInDim.

تُوسّع هذه الدالة حجم الصفيف وعدد أبعاده عن طريق تكرار البيانات في الصفيف.

BroadcastInDim(operand, out_dim_size, broadcast_dimensions)

الوسيطات النوع الدلالات
operand XlaOp الصفيف المطلوب تكراره
out_dim_size ArraySlice<int64> أحجام أبعاد الشكل المستهدَف
broadcast_dimensions ArraySlice<int64> السمة في الشكل المستهدَف التي تتطابق مع كل سمة من سمات شكل الم Operand

يشبه "البث"، ولكنه يسمح بإضافة سمات في أي مكان وتوسيع السمات الحالية التي يبلغ حجمها 1.

يتم بث operand إلى الشكل الموضّح في out_dim_size. تُعرِض broadcast_dimensions سمات operand إلى سمات الشكل المستهدَف، أي أنّه يتم ربط السمة i من الم Operand بالسمة broadcast_dimension[i] من شكل الإخراج. يجب أن تكون سمات operand بحجم 1 أو أن تكون بالحجم نفسه للسمة في شكل المخرج الذي تتمّ ربطها به. يتم ملء السمات المتبقية بسمات بحجم 1. بعد ذلك، يتمّ بثّ السمات المتدهورة على طول هذه السمات المتدهورة للوصول إلى شكل الإخراج. يتم وصف الدلالات بالتفصيل في صفحة البث.

الاتصال

يمكنك الاطّلاع أيضًا على XlaBuilder::Call.

تستدعي عملية حسابية باستخدام الوسيطات المحدّدة.

Call(computation, args...)

الوسيطات النوع الدلالات
computation XlaComputation حساب من النوع T_0, T_1, ..., T_{N-1} -> S مع N مَعلمة من نوع عشوائي
args تسلسل N XlaOp عدد N من الوسيطات من النوع العشوائي

يجب أن تتطابق عدد مَعلمات args وأنواعها مع مَعلمات computation. يُسمح بعدم توفّر args.

CompositeCall

يمكنك الاطّلاع أيضًا على XlaBuilder::CompositeCall.

تُغلِّف عملية مكوّنة من عمليات StableHLO أخرى، ويأخذ العنصر مدخلات وcomposite_attributes وينتج نتائج. يتم تنفيذ دلالات العملية من خلال سمة التحليل. يمكن استبدال العملية المركبة بتحليلها بدون تغيير دلالات البرنامج. في الحالات التي لا يوفّر فيها تضمين عملية التقسيم دلالات العملية نفسها، يُفضّل استخدام custom_call.

يُستخدَم حقل الإصدار (القيمة التلقائية هي 0) للإشارة إلى الحالات التي تتغيّر فيها دلالات العنصر المركب.

يتم تنفيذ هذه العملية على أنّها kCall مع السمة is_composite=true. يتم تحديد الحقل decomposition باستخدام السمة computation. تخزِّن سمات واجهة المستخدم السمات المتبقية التي تبدأ بالبادئة composite..

مثال على عملية CompositeCall:

f32[] call(f32[] %cst), to_apply=%computation, is_composite=true,
frontend_attributes = {
  composite.name="foo.bar",
  composite.attributes={n = 1 : i32, tensor = dense<1> : tensor<i32>},
  composite.version="1"
}

Call(computation, args..., name, composite_attributes, version)

الوسيطات النوع الدلالات
inputs XlaOp عدد متغيّر من القيم
name string اسم المكوّن المُركّب
composite_attributes اختياري string معجم اختياري لسمات منسقة في سلسلة
decomposition XlaComputation حساب من النوع T_0, T_1, ..., T_{N-1} -> S مع N مَعلمة من نوع عشوائي
version int64. تحديثات من رقم إلى إصدار لدلالات العملية المركبة

Cholesky

يمكنك الاطّلاع أيضًا على XlaBuilder::Cholesky.

تُحتسب تحليلة كولشيك لمجموعة من المصفوفات الإيجابية التحديد المتماثلة (هيرميتية).

Cholesky(a, lower)

الوسيطات النوع الدلالات
a XlaOp مصفوفة من النوع المركب أو النوع الكسري العشري مع أكثر من بُعدَين
lower bool ما إذا كنت تريد استخدام المثلث العلوي أو السفلي من a

إذا كان lower هو true، يتم احتساب المصفوفات الثلاثية السفلية l بحيث يكون a = l . l^T$. إذا كان lower هو false، يتم احتساب المصفوفات الثلاثية العلوية u بحيث \(a = u^T . u\).

لا تتم قراءة بيانات الإدخال إلا من المثلث السفلي/العلوي من a، استنادًا إلى قيمة lower. ويتم تجاهل القيم من المثلث الآخر. يتم عرض بيانات الإخراج في المثلث نفسه، أما القيم في المثلث الآخر فتكون محددة من خلال التنفيذ ويمكن أن تكون أيّ شيء.

إذا كان a يتضمّن أكثر من سمتَين، يتم التعامل مع a على أنّه مجموعة من المصفوفات، حيث تكون جميع السمتَين الثانويتَين باستثناء السمتَين الرئيسيتَين هما سمتَا المجموعة.

إذا لم تكن المصفوفة a متماثلة (هيرميتية) موجبة محددة، تكون النتيجة محددة من التنفيذ.

عقدة تقييد القيم

يمكنك الاطّلاع أيضًا على XlaBuilder::Clamp.

تحصر عاملًا ضمن النطاق بين الحد الأدنى والحد الأقصى.

Clamp(min, operand, max)

الوسيطات النوع الدلالات
min XlaOp صفيف من النوع T
operand XlaOp صفيف من النوع T
max XlaOp صفيف من النوع T

تُعطى الدالة معاملًا والحد الأدنى والحد الأقصى، وتُعرِض المعامل إذا كان في النطاق بين الحد الأدنى والحد الأقصى، أو تعرِض الحد الأدنى إذا كان المعامل أقل من هذا النطاق أو الحد الأقصى إذا كان المعامل أعلى من هذا النطاق. أي clamp(a, x, b) = min(max(a, x), b).

يجب أن تكون جميع المصفوفات الثلاث بالشكل نفسه. بدلاً من ذلك، يمكن أن يكون min و/أو max متغيّرًا متسلسلًا من النوع T، وذلك لأنّه شكل محظور من البث.

مثال على الكميتين min وmax:

let operand: s32[3] = {-1, 5, 9};
let min: s32 = 0;
let max: s32 = 6;
==>
Clamp(min, operand, max) = s32[3]{0, 5, 6};

تصغير

راجِع أيضًا XlaBuilder::Collapse وعملية tf.reshape.

تُدمج أبعاد الصفيف في سمة واحدة.

Collapse(operand, dimensions)

الوسيطات النوع الدلالات
operand XlaOp صفيف من النوع T
dimensions int64 متّجه مجموعة فرعية متسلسلة بترتيب معيّن من سمات T

تستبدِل دالة "التجميع" المجموعة الفرعية المحدّدة من سمات الم Operand بسمة واحدة. وسيطات الإدخال هي صفيف عشوائي من النوع T وأحد المتجهات الثابتة في وقت الترجمة لفهارس السمات. يجب أن تكون فهارس السمات مجموعة فرعية متسلسلة من سمات T بترتيب تصاعدي (من الأرقام الأقل إلى الأرقام الأعلى للسمات). وبالتالي، فإنّ {0, 1, 2} أو {0, 1} أو {1, 2} هي مجموعات سمات صالحة، ولكن {1, 0} أو {0, 2} ليست كذلك. ويتم استبدالها بسمة جديدة واحدة في الموضع نفسه في تسلسل السمات الذي تحلّ محلّه، مع حجم السمة الجديدة يساوي حاصل ضرب أحجام السمات الأصلية. إنّ الرقم الأصغر للسمة في dimensions هو السمة التي تتغيّر ببطء أكبر (الأكثر أهمية) في تداخل الحلقات الذي يدمج هذه السمات، والرقم الأعلى للسمة هو السمة التي تتغيّر بسرعة أكبر (الأكثر ثانوية). اطّلِع على عامل التشغيل tf.reshape إذا كنت بحاجة إلى مزيد من ترتيب التجميع العام.

على سبيل المثال، لنفترض أنّ v هي مصفوفة من 24 عنصرًا:

let v = f32[4x2x3] { { {10, 11, 12},  {15, 16, 17} },
{ {20, 21, 22},  {25, 26, 27} },
{ {30, 31, 32},  {35, 36, 37} },
{ {40, 41, 42},  {45, 46, 47} } };

// Collapse to a single dimension, leaving one dimension.
let v012 = Collapse(v, {0,1,2});
then v012 == f32[24] {10, 11, 12, 15, 16, 17,
20, 21, 22, 25, 26, 27,
30, 31, 32, 35, 36, 37,
40, 41, 42, 45, 46, 47};

// Collapse the two lower dimensions, leaving two dimensions.
let v01 = Collapse(v, {0,1});
then v01 == f32[4x6] { {10, 11, 12, 15, 16, 17},
{20, 21, 22, 25, 26, 27},
{30, 31, 32, 35, 36, 37},
{40, 41, 42, 45, 46, 47} };

// Collapse the two higher dimensions, leaving two dimensions.
let v12 = Collapse(v, {1,2});
then v12 == f32[8x3] { {10, 11, 12},
{15, 16, 17},
{20, 21, 22},
{25, 26, 27},
{30, 31, 32},
{35, 36, 37},
{40, 41, 42},
{45, 46, 47} };

CollectivePermute

يمكنك الاطّلاع أيضًا على XlaBuilder::CollectivePermute.

CollectivePermute هي عملية جماعية تُرسِل البيانات وتتلقّاها على مستوى النُسخ.

CollectivePermute(operand, source_target_pairs)

الوسيطات النوع الدلالات
operand XlaOp مصفوفة إدخال من n سمة
source_target_pairs <int64, int64> متّجه قائمة بأزواج (source_replica_id, target_replica_id) بالنسبة إلى كل زوج، يتم إرسال المُعامِل من النسخة المكرّرة للمصدر إلى النسخة المكرّرة للهدف.

يُرجى العلم أنّ هناك القيود التالية على source_target_pair:

  • يجب ألا يتضمّن أي زوجَين معرّف النسخة المستهدفة نفسه، ويجب ألا يتضمّنَا معرّف النسخة المصدر نفسه.
  • إذا لم يكن معرّف النسخة المتماثلة هدفًا في أيّ زوج، يكون الناتج في تلك النسخة المتماثلة هو مصفوفة تتكون من أصفار بالشكل نفسه للدخل.

دمج

يمكنك الاطّلاع أيضًا على XlaBuilder::ConcatInDim.

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

Concatenate(operands..., dimension)

الوسيطات النوع الدلالات
operands تسلسل N XlaOp صفائف N من النوع T ذات الأبعاد [L0, L1, ...]. يجب أن تكون N >= 1.
dimension int64 قيمة في النطاق [0, N) تُحدِّد اسم السمة التي سيتم تسلسلها بين operands

باستثناء dimension، يجب أن تكون جميع السمات متطابقة. ويعود سبب ذلك إلى أنّ XLA لا تتيح استخدام صفائف "مجزّأة". يُرجى العلم أيضًا أنّه لا يمكن تسلسل قيم 0 سمة (لأنّه من المستحيل تسمية السمة التي يتم التسلسل على طولها).

مثال أحادي الأبعاد:

Concat({ {2, 3}, {4, 5}, {6, 7} }, 0)
>>> {2, 3, 4, 5, 6, 7}

مثال على القياس ثنائي الأبعاد:

let a = {
{1, 2},
{3, 4},
{5, 6},
};
let b = {
{7, 8},
};
Concat({a, b}, 0)
>>> {
{1, 2},
{3, 4},
{5, 6},
{7, 8},
}

المخطّط:

الجملة الشرطية

يمكنك الاطّلاع أيضًا على XlaBuilder::Conditional.

Conditional(pred, true_operand, true_computation, false_operand, false_computation)

الوسيطات النوع الدلالات
pred XlaOp عدد صحيح من النوع PRED
true_operand XlaOp وسيطة من النوع \(T_0\)
true_computation XlaComputation XlaComputation من النوع \(T_0 \to S\)
false_operand XlaOp وسيطة من النوع \(T_1\)
false_computation XlaComputation XlaComputation من النوع \(T_1 \to S\)

تُنفِّذ true_computation إذا كانت pred هي true، وfalse_computation إذا كانت pred هي false، وتعرض النتيجة.

يجب أن تأخذ الدالة true_computation وسيطة واحدة من النوع \(T_0\) ، وسيتم استدعاؤها باستخدام true_operand الذي يجب أن يكون من النوع نفسه. يجب أن تأخذ الدالة false_computation وسيطة واحدة من النوع \(T_1\) ، وسيتم استدعاؤها باستخدام false_operand الذي يجب أن يكون من النوع نفسه. يجب أن يكون نوع القيمة المعروضة لكل من true_computation وfalse_computation متطابقًا.

يُرجى العِلم أنّه سيتم تنفيذ أحد الإجراءَين true_computation وfalse_computation فقط استنادًا إلى قيمة pred.

Conditional(branch_index, branch_computations, branch_operands)

الوسيطات النوع الدلالات
branch_index XlaOp عدد صحيح من النوع S32
branch_computations تسلسل N XlaComputation XlaComputations من النوع \(T_0 \to S , T_1 \to S , ..., T_{N-1} \to S\)
branch_operands تسلسل N XlaOp الوسيطات من النوع \(T_0 , T_1 , ..., T_{N-1}\)

تنفيذ branch_computations[branch_index] وعرض النتيجة إذا كان branch_index هو S32 أصغر من 0 أو أكبر من أو يساوي N، يتم تنفيذbranch_computations[N-1] كالفرع التلقائي.

يجب أن يقبل كل branch_computations[b] وسيطة واحدة من النوع \(T_b\) ، و سيتم استدعاؤه باستخدام branch_operands[b] الذي يجب أن يكون من النوع نفسه. يجب أن يكون نوع القيمة المعروضة لكل branch_computations[b] متطابقًا.

يُرجى العِلم أنّه سيتم تنفيذ إجراء واحد فقط من branch_computations استنادًا إلى قيمة branch_index.

Conv (التفاف)

يمكنك الاطّلاع أيضًا على XlaBuilder::Conv.

مثل ConvWithGeneralPadding، ولكن يتم تحديد الحشو بطريقة مختصرة على النحو التالي: سواء كان SAME أو VALID. تعمل إضافة SAME على إضافة أصفار إلى الإدخال (lhs) لكي يكون شكل الإخراج مماثلاً لشكل الإدخال في حال عدم مراعاة الخطوات. يعني وضع الحشو الصالح ببساطة عدم وضع حشو.

ConvWithGeneralPadding (التفاف)

يمكنك الاطّلاع أيضًا على XlaBuilder::ConvWithGeneralPadding.

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

الوسيطات النوع الدلالات
lhs XlaOp صفيف من الإدخالات ببعد (n+2)
rhs XlaOp صفيف من الأبعاد (n+2) لأوزان النواة
window_strides ArraySlice<int64> مصفوفة ثنائية الأبعاد لخطوات النواة
padding ArraySlice< pair<int64,int64>> صفيف n-d من الحشو (low, high)
lhs_dilation ArraySlice<int64> صفيف عامل تمدد lhs ذي الأبعاد n
rhs_dilation ArraySlice<int64> صفيف عامل تمدد يسار الجملة ببعد n
feature_group_count int64 عدد مجموعات الميزات
batch_group_count int64 عدد مجموعات الدفعات

لنفترض أنّ n هو عدد السمات المكانية. وسيطة lhs هي صفيف ببعد (n+2) يصف المنطقة الأساسية. يُعرف هذا باسم الإدخال، على الرغم من أنّ الجانب الأيمن هو إدخال أيضًا. في الشبكة العصبية، هذه هي عمليات تنشيط الإدخال. في ما يلي السمات n+2 بالترتيب التالي:

  • batch: يمثّل كل إحداثي في هذه السمة إدخالًا مستقلاً يتم إجراء عملية التفاف عليه.
  • z/depth/features: يرتبط بكل موضع (y,x) في المنطقة الأساسية متجه ، والذي يدخل في هذه السمة.
  • spatial_dims: تصف السمات المكانية n التي تحدّد المنطقة الأساسية التي تتحرّك فيها النافذة.

الوسيطة rhs هي صفيف من (n+2) سمة يصف ملف التمويه/النواة/النافذة. وتكون السمات على النحو التالي:

  • output-z: سمة z للناتج
  • input-z: يجب أن يساوي حجم هذه السمة مضروبًا في feature_group_count حجم سمة z في lhs.
  • spatial_dims: تصف السمة n الأبعاد المكانية التي تحدّد النافذة n-d التي تتحرّك في جميع أنحاء المنطقة الأساسية.

تحدِّد الوسيطة window_strides خطوة نافذة الالتفاف في السمات المكانية. على سبيل المثال، إذا كانت الخطوة في السمة المكانية الأولى هي 3، لا يمكن وضع النافذة إلا عند الإحداثيات التي يكون فيها الفهرس المكاني الأول قابلاً للقسمة على 3.

تحدِّد الوسيطة padding مقدار الحشو بالصفر الذي سيتم تطبيقه على المساحة الأساسية. يمكن أن تكون قيمة الحشو سالبة، وتشير القيمة المطلقة للحشو السالب إلى عدد العناصر التي يجب إزالتها من السمة المحدّدة قبل إجراء عملية التفاف. padding[0] تحدّد الحشو لسمة y وpadding[1] تحدّد الحشو لسمة x. يتضمّن كل زوج الحشو المنخفض كأول عنصر والحشو العالي كثاني عنصر. يتم تطبيق الحشو المنخفض في اتجاه الفواصل الدنيا بينما يتم تطبيق الحشو المُرتفع في اتجاه الفواصل الأعلى. على سبيل المثال، إذا كان padding[1] يساوي (2,3)، سيتمّ إضافة صفرَين على يمين العنصر و ثلاثة أصفار على يساره في السمة المكانية الثانية. إنّ استخدام الحشو هو معادل لإدخال قيم الصفر نفسها في الإدخال (lhs) قبل إجراء عملية التفاف.

تحدّد وسيطتا lhs_dilation وrhs_dilation عامل التمدد الذي يتم تطبيقه على lhs وrhs على التوالي في كلّ سمة مكانية. إذا كان عامل التمدد في سمة مكانية هو d، يتم تلقائيًا وضع d-1 من الفتحات بين كل إدخال في تلك السمة، ما يؤدي إلى زيادة حجم الصفيف. يتم ملء الفراغات بقيمة لا تؤدي إلى أيّ إجراء، ويعني ذلك بالنسبة إلى تصفية المُركّب الأصفار.

يُعرف تمدد الجانب الأيمن من المعادلة أيضًا باسم "التفاف atrous". لمزيد من التفاصيل، يُرجى الاطّلاع على tf.nn.atrous_conv2d. ويُعرف تمدد الجانب الأيسر من المعادلة أيضًا باسم التفاف المُعاد. لمزيد من التفاصيل، يُرجى الاطّلاع على tf.nn.conv2d_transpose.

يمكن استخدام الوسيطة feature_group_count (القيمة التلقائية 1) للعمليات المتعلّقة بالالتفاف المُجمَّع. يجب أن يكون feature_group_count مقسومًا لكل من سمة الإدخال وسمة الإخراج. إذا كانت قيمة feature_group_count أكبر من 1، يعني ذلك أنّه من الناحية المفهومية، يتم تقسيم سمة المدخلات والسمات الناتجة rhs وسمة الناتجة بالتساوي إلى العديد من feature_group_count المجموعات، وتتألف كل مجموعة من تسلسل فرعي متتالي من السمات. يجب أن تكون سمة سمة ميزة الإدخال rhs مساوية لسمة سمة ميزة الإدخال lhs مقسومة على feature_group_count (كي يكون لها حجم مجموعة من ميزات الإدخال). تُستخدَم المجموعات i معًا لاحتساب feature_group_count للعديد من عمليات التفاف الصور المنفصلة. يتم تسلسل نتائج عمليات الدمج هذه معًا في سمة ميزة الإخراج.

بالنسبة إلى الالتفاف المتعمّق، سيتم ضبط الوسيطة feature_group_count على سمة ميزة الإدخال، وسيتم إعادة تشكيل الفلتر من [filter_height, filter_width, in_channels, channel_multiplier] إلى [filter_height, filter_width, 1, in_channels * channel_multiplier]. لمزيد من التفاصيل، يُرجى الاطّلاع على tf.nn.depthwise_conv2d.

يمكن استخدام الوسيطة batch_group_count (القيمة التلقائية 1) للفلاتر المجمّعة أثناء الانتشار العكسي. يجب أن يكون batch_group_count مقسومًا لقياس حجم سمة الحزمة lhs (الإدخال). إذا كانت قيمة batch_group_count أكبر من 1، يعني ذلك أنّ سمة مجموعة الأركان الأساسية للإخراج يجب أن تكون بحجم input batch / batch_group_count. يجب أن يكون batch_group_count مقسومًا لحجم العنصر الناتج.

يتضمّن شكل الإخراج السمات التالية بالترتيب التالي:

  • batch: يجب أن يساوي حجم هذه السمة مضروبًا في batch_group_count حجم سمة batch في lhs.
  • z: الحجم نفسه لسمة output-z في النواة (rhs).
  • spatial_dims: قيمة واحدة لكل موضع صالح للنافذة التدرّجية.

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

يتم تحديد مواضع النافذة التجميعية الصالحة من خلال الخطوات وحجم المنطقة الأساسية بعد الحشو.

لوصف ما تفعله عملية التفاف، نأخذ عملية التفاف ثنائية الأبعاد ونختار بعض إحداثيات batch وz وy وx ثابتة في الإخراج. و(y,x) هو موضع أحد أركان النافذة ضمن منطقة القاعدة (مثلاً، (y,x) هو العلوي الأيمن، استنادًا إلى كيفية تفسيرك للأبعاد المكانية). لدينا الآن نافذة ثنائية الأبعاد، تم أخذها من منطقة القاعدة، حيث تكون كل نقطة ثنائية الأبعاد مرتبطة بأحد vektors الأحادي الأبعاد، وبالتالي نحصل على مربّع ثلاثي الأبعاد. من نواة الالتفاف، بما أنّنا ثبّتنا إحداثي الإخراج z، لدينا أيضًا مربّع ثلاثي الأبعاد. يتضمّن المربّعَان السمات نفسها، لذا يمكننا الحصول على مجموع حاصل ضرب كل عنصر في المربّعَين (على غرار حاصل الضرب النقطي). هذه هي قيمة الإخراج.

يُرجى العلم أنّه إذا كان output-z هو مثلاً، 5، ثمّ ينتج كل موضع من النافذة 5 قيم في الناتج في سمة z من الناتج. تختلف هذه القيم حسب الجزء المستخدَم من نواة التفاف - هناك مربّع ثلاثي الأبعاد من القيم المستخدَمة لكل إحداثي output-z. وبالتالي، يمكنك اعتبارها 5 عمليات تلافيف منفصلة باستخدام فلتر مختلف لكل منها.

في ما يلي رمز زائف لدمج ثنائي الأبعاد مع الحشو والخطوات:

for (b, oz, oy, ox) {  // output coordinates
  value = 0;
  for (iz, ky, kx) {  // kernel coordinates and input z
    iy = oy*stride_y + ky - pad_low_y;
    ix = ox*stride_x + kx - pad_low_x;
    if ((iy, ix) inside the base area considered without padding) {
      value += input(b, iz, iy, ix) * kernel(oz, iz, ky, kx);
    }
  }
  output(b, oz, oy, ox) = value;
}

ConvertElementType

يمكنك الاطّلاع أيضًا على XlaBuilder::ConvertElementType.

على غرار static_cast على مستوى العنصر في C++، تُجري عملية تحويل على مستوى العنصر من شكل بيانات إلى شكل مستهدَف. يجب أن تتم مطابقة السمات، ويكون التحويل على مستوى العنصر، على سبيل المثال، تصبح عناصر s32 عناصر f32 من خلال إجراء تحويل s32 إلى f32.

ConvertElementType(operand, new_element_type)

الوسيطات النوع الدلالات
operand XlaOp صفيف من النوع T مع سمات D
new_element_type PrimitiveType النوع U

يجب أن تتطابق أبعاد الم Operand وشكل الهدف. يجب ألا تكون أنواع عنصرَي المصدر والوجهة مجموعات ثنائية.

سيؤدي تحويل مثل T=s32 إلى U=f32 إلى تنفيذ روتين تحويل عدد صحيح إلى عدد عشري عادي، مثل التقريب إلى أقرب عدد صحيح زوجي.

let a: s32[3] = {0, 1, 2};
let b: f32[3] = convert(a, f32);
then b == f32[3]{0.0, 1.0, 2.0}

CrossReplicaSum

تُجري AllReduce عملية حسابية للجمع.

CustomCall

يمكنك الاطّلاع أيضًا على XlaBuilder::CustomCall.

استدعاء دالة يقدّمها المستخدم ضمن عملية حسابية

CustomCall(target_name, args..., shape)

الوسيطات النوع الدلالات
target_name string اسم الدالة سيتمّ إصدار تعليمات اتصال تستهدف اسم الرمز هذا.
args تسلسل N XlaOp وسيطات N من النوع العشوائي، والتي سيتم تمريرها إلى الدالة
shape Shape شكل ناتج الدالة

يكون توقيع الدالة هو نفسه، بغض النظر عن عدد المَعلمات أو نوعها:

extern "C" void target_name(void* out, void** in);

على سبيل المثال، إذا تم استخدام CustomCall على النحو التالي:

let x = f32[2] {1,2};
let y = f32[2x3] { {10, 20, 30}, {40, 50, 60} };

CustomCall("myfunc", {x, y}, f32[3x3])

في ما يلي مثال على تنفيذ myfunc:

extern "C" void myfunc(void* out, void** in) {
  float (&x)[2] = *static_cast<float(*)[2]>(in[0]);
  float (&y)[2][3] = *static_cast<float(*)[2][3]>(in[1]);
  EXPECT_EQ(1, x[0]);
  EXPECT_EQ(2, x[1]);
  EXPECT_EQ(10, y[0][0]);
  EXPECT_EQ(20, y[0][1]);
  EXPECT_EQ(30, y[0][2]);
  EXPECT_EQ(40, y[1][0]);
  EXPECT_EQ(50, y[1][1]);
  EXPECT_EQ(60, y[1][2]);
  float (&z)[3][3] = *static_cast<float(*)[3][3]>(out);
  z[0][0] = x[1] + y[1][0];
  // ...
}

يجب ألا يكون للدالة المقدَّمة من المستخدِم أيّ تأثيرات جانبية، ويجب أن يكون تنفيذها معادلًا.

نقطة

يمكنك الاطّلاع أيضًا على XlaBuilder::Dot.

Dot(lhs, rhs)

الوسيطات النوع الدلالات
lhs XlaOp صفيف من النوع T
rhs XlaOp صفيف من النوع T

تعتمد الدلالات الدقيقة لهذه العملية على ترتيبات المَعلمات:

الإدخال الناتج الدلالات
المتّجه [n] dot المتّجه [n] الكمية القياسية حاصل ضرب المتّجهَين
مصفوفة [m x k] dot متجه [k] المتّجه [م] ضرب المصفوفة في المتجه
المصفوفة [m x k] dot المصفوفة [k x n] مصفوفة [m x n] ضرب مصفوفة في مصفوفة

تُجري العملية مجموع المنتجات على السمة الثانية من lhs (أو السمة الأولى إذا كانت تحتوي على سمة واحدة) والسمة الأولى من rhs. هذه هي السمات "المتعاقد عليها". يجب أن تكون الأبعاد المتعاقد عليها لكل من lhs وrhs بالحجم نفسه. في الممارسة العملية، يمكن استخدامه لإجراء ضربات نقطية بين المتجهات أو عمليات ضرب المتجهات/المصفوفات أو عمليات ضرب المصفوفات/المصفوفات.

DotGeneral

يمكنك الاطّلاع أيضًا على XlaBuilder::DotGeneral.

DotGeneral(lhs, rhs, dimension_numbers)

الوسيطات النوع الدلالات
lhs XlaOp صفيف من النوع T
rhs XlaOp صفيف من النوع T
dimension_numbers DotDimensionNumbers أرقام سمات العقد والدفعات

تشبه Dot، ولكنها تسمح بتحديد أرقام سمات التعاقد والمجموعة لكل من lhs وrhs.

حقول DotDimensionNumbers النوع الدلالات
lhs_contracting_dimensions int64 متكرّر lhs سمة التعاقد الأرقام
rhs_contracting_dimensions int64 متكرّر rhs سمة التعاقد الأرقام
lhs_batch_dimensions int64 متكرّر lhs سمة المجموعة الأرقام
rhs_batch_dimensions int64 متكرّر rhs سمة المجموعة الأرقام

تُجري دالة DotGeneral مجموع المنتجات على السمات المتعاقدة المحدّدة في dimension_numbers.

لا يلزم أن تكون أرقام سمات العقد المرتبطة من lhs وrhs متطابقة، ولكن يجب أن تكون لها أحجام السمات نفسها.

مثال على أرقام السمات المتعاقدة:

lhs = { {1.0, 2.0, 3.0},
{4.0, 5.0, 6.0} }

rhs = { {1.0, 1.0, 1.0},
{2.0, 2.0, 2.0} }

DotDimensionNumbers dnums;
dnums.add_lhs_contracting_dimensions(1);
dnums.add_rhs_contracting_dimensions(1);

DotGeneral(lhs, rhs, dnums) -> { {6.0, 12.0},
{15.0, 30.0} }

يجب أن تكون أحجام سمات الدفعات المرتبطة من lhs وrhs متطابقة.

مثال على أرقام سمات الحِزم (حجم الحزمة 2، مصفوفات 2×2):

lhs = { { {1.0, 2.0},
{3.0, 4.0} },
{ {5.0, 6.0},
{7.0, 8.0} } }

rhs = { { {1.0, 0.0},
{0.0, 1.0} },
{ {1.0, 0.0},
{0.0, 1.0} } }

DotDimensionNumbers dnums;
dnums.add_lhs_contracting_dimensions(2);
dnums.add_rhs_contracting_dimensions(1);
dnums.add_lhs_batch_dimensions(0);
dnums.add_rhs_batch_dimensions(0);

DotGeneral(lhs, rhs, dnums) -> { { {1.0, 2.0},
{3.0, 4.0} },
{ {5.0, 6.0},
{7.0, 8.0} } }
الإدخال الناتج الدلالات
[b0, m, k] dot [b0, k, n] [b0, m, n] عمليات الضرب الحسابي للمصفوفات في حِزم
[b0, b1, m, k] dot [b0, b1, k, n] [b0, b1, m, n] عمليات الضرب الحسابي للمصفوفات في حِزم

ويترتب على ذلك أنّ رقم السمة الناتج يبدأ بسمة المجموعة، ثمّ سمة lhs غير المتعاقدة/غير المخصّصة للمجموعات، ثمّ سمة rhs غير المتعاقدة/غير المخصّصة للمجموعات.

DynamicSlice

يمكنك الاطّلاع أيضًا على XlaBuilder::DynamicSlice.

تستخرج دالة DynamicSlice مصفوفة فرعية من مصفوفة الإدخال في العنصر الديناميكي start_indices. يتم تمرير حجم الشريحة في كل سمة في size_indices، التي تحدّد نقطة نهاية فواصل الشرائح الحصرية في كل سمة: [start, start + size). يجب أن يكون شكل start_indices أحادي الأبعاد، وأن يكون حجم السمة مساويًا لعدد سمات operand.

DynamicSlice(operand, start_indices, size_indices)

الوسيطات النوع الدلالات
operand XlaOp صفيف من N سمة من النوع T
start_indices تسلسل N XlaOp قائمة بـ N عدد صحيح سكالري يحتوي على الفواصل الزمنية لبداية الشريحة لكل سمة يجب أن تكون القيمة أكبر من أو تساوي صفرًا.
size_indices ArraySlice<int64> قائمة بـ N عدد من الأعداد الصحيحة تحتوي على حجم الشريحة لكل سمة يجب أن تكون كل قيمة أكبر من الصفر بوضوح، ويجب أن يكون البدء + الحجم أقل من أو يساوي حجم السمة لتجنُّب التفاف القيمة على باقي حجم السمة.

يتم احتساب فهارس الشريحة الفعّالة من خلال تطبيق التحويل التالي على كل فهرس i في [1, N) قبل إجراء الشريحة:

start_indices[i] = clamp(start_indices[i], 0, operand.dimension_size[i] - size_indices[i])

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

مثال أحادي الأبعاد:

let a = {0.0, 1.0, 2.0, 3.0, 4.0}
let s = {2}

DynamicSlice(a, s, {2}) produces:
{2.0, 3.0}

مثال على القياس ثنائي الأبعاد:

let b =
{ {0.0,  1.0,  2.0},
{3.0,  4.0,  5.0},
{6.0,  7.0,  8.0},
{9.0, 10.0, 11.0} }
let s = {2, 1}

DynamicSlice(b, s, {2, 2}) produces:
{ { 7.0,  8.0},
{10.0, 11.0} }

DynamicUpdateSlice

يمكنك الاطّلاع أيضًا على XlaBuilder::DynamicUpdateSlice.

تُنشئ دالة DynamicUpdateSlice نتيجةً هي قيمة صفيف الإدخال operand، مع استبدال شريحة update في start_indices. يحدِّد شكل update شكل الصفيف الفرعي للنتيجة التي يتم تعديلها. يجب أن يكون شكل start_indices أحادي الأبعاد، وأن يكون حجم السمة مساويًا لعدد سمات operand.

DynamicUpdateSlice(operand, update, start_indices)

الوسيطات النوع الدلالات
operand XlaOp صفيف من N سمة من النوع T
update XlaOp صفيف من N سمة من النوع T يحتوي على تعديل الشريحة يجب أن تكون كل سمة من سمات شكل التعديل أكبر من الصفر بدقة، ويجب أن تكون القيمة "البداية" + القيمة "التعديل" أقل من أو تساوي حجم الم Operand لكل سمة لتجنُّب إنشاء فهارس تعديل خارج الحدود.
start_indices تسلسل N XlaOp قائمة بـ N عدد صحيح سكالري يحتوي على الفواصل الزمنية لبداية الشريحة لكل سمة يجب أن تكون القيمة أكبر من أو تساوي صفرًا.

يتم احتساب فهارس الشريحة الفعّالة من خلال تطبيق التحويل التالي على كل فهرس i في [1, N) قبل إجراء الشريحة:

start_indices[i] = clamp(start_indices[i], 0, operand.dimension_size[i] - update.dimension_size[i])

يضمن ذلك أنّ الشريحة المعدَّلة تكون دائمًا ضمن الحدود بالنسبة إلى صفيف المعامل. إذا كانت الشريحة ضمن الحدود قبل تطبيق التحويل، لن يكون للتحويل أي تأثير.

مثال أحادي الأبعاد:

let a = {0.0, 1.0, 2.0, 3.0, 4.0}
let u = {5.0, 6.0}
let s = {2}

DynamicUpdateSlice(a, u, s) produces:
{0.0, 1.0, 5.0, 6.0, 4.0}

مثال على القياس ثنائي الأبعاد:

let b =
{ {0.0,  1.0,  2.0},
{3.0,  4.0,  5.0},
{6.0,  7.0,  8.0},
{9.0, 10.0, 11.0} }
let u =
{ {12.0,  13.0},
{14.0,  15.0},
{16.0,  17.0} }

let s = {1, 1}

DynamicUpdateSlice(b, u, s) produces:
{ {0.0,  1.0,  2.0},
{3.0, 12.0, 13.0},
{6.0, 14.0, 15.0},
{9.0, 16.0, 17.0} }

العمليات الحسابية الثنائية على مستوى العنصر

يمكنك الاطّلاع أيضًا على XlaBuilder::Add.

تتوفّر مجموعة من العمليات الحسابية الثنائية على مستوى العنصر.

Op(lhs, rhs)

حيث يكون Op أحد الدوالّ التالية: Add (الجمع)، أو Sub(الطرح)، أو Mul (العملية الحسابية الضرب)، أو Div (العملية الحسابية القسمة)، أو Pow (العملية الحسابية الأس)، أو Rem (الباقي)، أو Max (الحد الأقصى)، أو Min (الحد الأدنى)، أو And (الدالة المنطقية "و")، أو Or (الدالة المنطقية "أو")، أو Xor (الدالة المنطقية "خيار أو")، أو ShiftLeft (الدالة الحسابية "الترقيم الثنائي لليمين")، أو ShiftRightArithmetic (الدالة الحسابية "الترقيم الثنائي لليسار")، أو ShiftRightLogical (الدالة المنطقية "الترقيم الثنائي لليسار")، أو Atan2 (الدالة "الظل القاطع" التي تستخدِم مَعلمتَين)، أو Complex (الدالة التي تجمع الأجزاء الحقيقية والخيالية في عدد مركب)

الوسيطات النوع الدلالات
lhs XlaOp المعامل على يمين العلامة: صفيف من النوع T
rhs XlaOp المعامل على يسار العلامة: صفيف من النوع T

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

عندما يكون Op هو Rem، يتم أخذ علامة النتيجة من المقسوم، وتكون قيمة النتيجة المطلقة دائمًا أقل من القيمة المطلقة للمقسوم عليه.

يؤدي تعذُّر قسمة الأعداد الصحيحة (قسمة/باقي القسمة/باقي القسمة بعلامة/بدون علامة على الصفر أو باقي القسمة/باقي القسمة بعلامةINT_SMIN مع -1) إلى إنشاء قيمة يتم تحديدها أثناء التنفيذ.

يتوفّر خيار بديل يتيح البث بتنسيقات مختلفة لهذه العمليات:

Op(lhs, rhs, broadcast_dimensions)

حيث يكون Op هو نفسه كما هو موضّح أعلاه. يجب استخدام هذا الصيغة من العملية للعمليات الحسابية بين صفائف من الرتب المختلفة (مثل إضافةermatix إلى متجه).

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

عمليات المقارنة على مستوى العنصر

يمكنك الاطّلاع أيضًا على XlaBuilder::Eq.

تتوفّر مجموعة من عمليات المقارنة الثنائية العادية لكل عنصر. يُرجى العلم أنّ قواعد مقارنة الأعداد الكسورية IEEE 754 العادية تنطبق عند مقارنة أنواع الأعداد الكسورية.

Op(lhs, rhs)

حيث يكون Op أحد القيم Eq (يساوي)، أو Ne (لا يساوي)، أو Ge (أكبر من أو يساوي)، أو Gt (أكبر من)، أو Le (أصغر من أو يساوي)، أو Lt (أصغر من). توفّر مجموعة أخرى من عوامل التشغيل، وهي EqTotalOrder وNeTotalOrder وGeTotalOrder وGtTotalOrder وLeTotalOrder وLtTotalOrder، الوظائف نفسها، باستثناء أنّها تتيح أيضًا ترتيبًا إجماليًا على الأرقام المتغيرة النقطة، من خلال فرض -NaN < -Inf < -Finite < -0 < +0 < +Finite < +Inf < +NaN.

الوسيطات النوع الدلالات
lhs XlaOp المعامل على يمين العلامة: صفيف من النوع T
rhs XlaOp المعامل على يسار العلامة: صفيف من النوع T

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

يتوفّر خيار بديل يتيح البث بتنسيقات مختلفة لهذه العمليات:

Op(lhs, rhs, broadcast_dimensions)

حيث يكون Op هو نفسه كما هو موضّح أعلاه. يجب استخدام هذا الصيغة من العملية لعمليات المقارنة بين صفائف من الرتب المختلفة (مثل إضافةermat إلى متجه).

عامل التشغيل broadcast_dimensions الإضافي هو شريحة من الأعداد الصحيحة التي تحدِّد السمات التي سيتم استخدامها لبث عوامل التشغيل. يتم وصف الدلالات بالتفصيل في صفحة البث.

الدوالّ الأحادية لكل عنصر

يتيح XlaBuilder الدوالّ الأحادية العنصر التالية:

Abs(operand) القيمة المطلقة لكل عنصر x -> |x|.

Cbrt(operand) عملية الجذر التكعيبي لكل عنصر x -> cbrt(x).

Ceil(operand) دالة ceil على مستوى العنصر x -> ⌈x⌉.

Clz(operand) احتساب الأصفار البادئة لكل عنصر على حدة

Cos(operand) دالة الجيب الزائدي لكل عنصر x -> cos(x)

Erf(operand) دالة الخطأ لكل عنصر x -> erf(x) حيث

\(\text{erf}(x) = \frac{2}{\sqrt{\pi} }\int_0^x e^{-t^2} \, dt\).

Exp(operand) دالة أسية طبيعية على مستوى العنصر x -> e^x.

Expm1(operand) الأسّ الطبيعي لكل عنصر مطروحًا منه واحد x -> e^x - 1

Floor(operand) الحد الأدنى لكل عنصر x -> ⌊x⌋.

Imag(operand) الجزء التخيلي لكل عنصر من عناصر شكل معقد (أو حقيقي). x -> imag(x). إذا كان الم Operand من النوع الكسري العائم، يتم عرض القيمة 0.

IsFinite(operand) يختبر ما إذا كان كل عنصر من operand محدودًا، أي ليس موجب أو سالب ما لا نهاية، وليس NaN. تعرِض صفيفًا من قيم PRED بالشكل نفسه للإدخال، حيث يكون كل عنصر true إذا كان عنصر الإدخال المقابل محدودًا فقط.

Log(operand) اللوغاريتم الطبيعي لكل عنصر x -> ln(x)

Log1p(operand) اللوغاريتم الطبيعي المتغيّر على مستوى العنصر x -> ln(1+x).

Logistic(operand) حساب الدالة اللوجستية على مستوى العنصر x -> logistic(x).

Neg(operand) النفي على مستوى العنصر x -> -x.

Not(operand) رمز المعامل المنطقي not (ليس) على مستوى العنصر x -> !(x)

تحسب دالة PopulationCount(operand) عدد الوحدات بت التي تم ضبطها في كل عنصر من operand.

Real(operand) الجزء الحقيقي لكل عنصر من شكل مركّب (أو حقيقي). x -> real(x). إذا كان المعامل من النوع الكسري، يتم عرض القيمة نفسها.

Round(operand) التقريب حسب العنصر، مع الابتعاد عن الصفر

RoundNearestEven(operand) التقريب حسب العنصر، يتم ربطه بأقرب عدد زوجي.

Rsqrt(operand) مقلوب عملية الجذر التربيعي لكل عنصر x -> 1.0 / sqrt(x).

Sign(operand) عملية التوقيع على كل عنصر x -> sgn(x) حيث

\[\text{sgn}(x) = \begin{cases} -1 & x < 0\\ -0 & x = -0\\ NaN & x = NaN\\ +0 & x = +0\\ 1 & x > 0 \end{cases}\]

باستخدام عامل تشغيل المقارنة لنوع العنصر operand.

Sin(operand) دالة الجيبّ المنتظم على مستوى العنصر x -> sin(x).

Sqrt(operand) عملية الجذر التربيعي لكل عنصر x -> sqrt(x).

Tan(operand) دالة ظلّية على مستوى العنصر x -> tan(x).

Tanh(operand) دالة الظل الزائدي لكل عنصر x -> tanh(x)

الوسيطات النوع الدلالات
operand XlaOp المعامل للدالة

يتم تطبيق الدالة على كل عنصر في الصفيف operand، ما يؤدي إلى الحصول على صفيف بالشكل نفسه. يُسمح بأن يكون operand عددًا متّجهًا (ببعد 0).

Fft

تُنفِّذ عملية XLA FFT تحويلات فورييه المباشرة والعكسية ل المدخلات/المخرجات الحقيقية والمركّبة. يمكن استخدام تحويلات فورييه المتعدّدة الأبعاد على ما يصل إلى 3 محاور.

يمكنك الاطّلاع أيضًا على XlaBuilder::Fft.

الوسيطات النوع الدلالات
operand XlaOp الصفيف الذي نجري عليه تحويل فورييه
fft_type FftType اطّلِع على الجدول أدناه.
fft_length ArraySlice<int64> أطوال النطاق الزمني للأعمدة التي يتم تحويلها. ويلزم ذلك على وجه الخصوص لاستخدام IRFFT لضبط الحجم المناسب للمحور الداخلي، لأنّ RFFT(fft_length=[16]) له شكل الإخراج نفسه مثل RFFT(fft_length=[17]).
FftType الدلالات
FFT تحويل فورييه المباشر للإشارة المركّبة إلى إشارة مركّبة الشكل لم يتغيّر.
IFFT تحويل فورييه العكسي من المعقد إلى المعقد الشكل لم يتغيّر.
RFFT تحويل فورييه المباشر للأرقام الحقيقية إلى مركبة يتم تقليل شكل المحور الداخلي إلى fft_length[-1] // 2 + 1 إذا كانت fft_length[-1] قيمة غير صفرية، مع حذف الجزء المزدوج العكسي للإشارة المحوَّلة بعد تردد Nyquist.
IRFFT تحويل فورييه العكسي للأرقام الحقيقية إلى مركبة (أي يأخذ أرقامًا مركبة ويعرض أرقامًا حقيقية). يتم توسيع شكل المحور الداخلي إلى fft_length[-1] إذا كانت fft_length[-1] قيمة غير صفرية، ما يشير إلى جزء الإشارة المحوَّلة خارج تردد Nyquist من العنصر المرافق العكسي لإدخالات 1 إلى fft_length[-1] // 2 + 1.

تحويل فورييه المتعدّد الأبعاد

عند تقديم أكثر من fft_length واحد، يكون ذلك معادلاً لتطبيق تسلسل من عمليات تحويل فورييه السريع على كل محور من المحاور الداخلية. يُرجى العلم أنّه في الحالتَين الحقيقية إلى المعقدة والمعقدة إلى الحقيقية، يتم أولاً (بشكل فعّال) تحويل محور التحويل الداخلي (RFFT) ثم تحويل IRFFT، ولهذا السبب، فإنّ محور التحويل الداخلي هو الذي يغيّر الحجم. ستكون عمليات تحويل المحاور الأخرى بعد ذلك معقدة->معقدة.

تفاصيل التنفيذ

تستند تحويلة فورييه لرقائق وحدة المعالجة المركزية إلى TensorFFT من Eigen. تستخدم تحويلة فورييه باستخدام وحدة معالجة الرسومات cuFFT.

Gather

تعمل عملية التجميع في XLA على تجميع عدة شرائح (كل شريحة في موضع تشغيل مختلف محتمل) من صفيف الإدخال.

الدلالات العامة

يمكنك الاطّلاع أيضًا على XlaBuilder::Gather. للحصول على وصف أكثر وضوحًا، يُرجى الاطّلاع على قسم "الوصف غير الرسمي" أدناه.

gather(operand, start_indices, offset_dims, collapsed_slice_dims, slice_sizes, start_index_map)

الوسيطات النوع الدلالات
operand XlaOp الصفيف الذي نجمعه منه
start_indices XlaOp صفيف يحتوي على الفهارس البادئة للشرائح التي نجمعها
index_vector_dim int64 السمة في start_indices التي "تحتوي" على الفهارس البادئة. يُرجى الاطّلاع أدناه على وصف مفصّل.
offset_dims ArraySlice<int64> مجموعة السمات في شكل الإخراج التي يتمّ إزاحتها إلى صفيف تمّ تقطيعه من الم Operand
slice_sizes ArraySlice<int64> slice_sizes[i] هي حدود الشريحة للسمة i.
collapsed_slice_dims ArraySlice<int64> مجموعة السمات في كل شريحة تم تصغيرها يجب أن يكون حجم هذه السمات هو 1.
start_index_map ArraySlice<int64> خريطة تصف كيفية ربط الفواصل في start_indices بالفواصل القانونية في الم Operand
indices_are_sorted bool ما إذا كان من المؤكد أن يتم ترتيب الفهارس حسب المُتصل

لتسهيل الأمر، نضع علامة batch_dims على السمات في صفيف الإخراج وليس في offset_dims.

الناتج هو صفيف يتضمّن batch_dims.size + offset_dims.size سمة.

يجب أن يساوي operand.rank مجموع offset_dims.size و collapsed_slice_dims.size. يجب أيضًا أن تكون slice_sizes.size مساوية operand.rank.

إذا كان index_vector_dim يساوي start_indices.rank، نعتبر ضمنيًا أنّه لعنصر start_indices سمة 1 متأخرة (أي إذا كان start_indices من شكل [6,7] وكان index_vector_dim يساوي 2، نعتبر ضمنيًا أنّ شكل start_indices هو [6,7,1]).

يتم احتساب حدود صفيف الإخراج على طول السمة i على النحو التالي:

  1. إذا كانت i متوفّرة في batch_dims (أي تساوي batch_dims[k] ل بعض k)، نختار حدود السمة المقابلة من start_indices.shape، مع تخطّي index_vector_dim (أي اختيار start_indices.shape.dims[k] إذا كان k < index_vector_dim و start_indices.shape.dims[k+1] في غير ذلك).

  2. إذا كان i متوفّرًا في offset_dims (أي يساوي offset_dims[k] ل بعض k)، نختار الحدّ المقابل من slice_sizes بعد الأخذ في الاعتبار collapsed_slice_dims (أي نختار adjusted_slice_sizes[k] حيث يكون adjusted_slice_sizes هو slice_sizes مع إزالة الحدود في الفهارس collapsed_slice_dims).

من الناحية الرسمية، يتم حساب فهرس الم OperandIn المرتبط بفهرس ناتج معيّنOut على النحو التالي:

  1. لنفترض أنّ G = { Out[k] لـ k في batch_dims }. استخدِم G لقطع S عمود كهذا بحيث يكون S[i] = start_indices[Combine(G, i)] حيث يُدخِل دالة Combine(A, b) العنصر b في الموضع index_vector_dim في A. يُرجى العلم أنّه تم تحديد هذا الإجراء بشكل جيد حتى إذا كانت G فارغة: إذا كانت G فارغة، تكون S = start_indices.

  2. أنشئ فهرسًا أوليًا، Sin، في operand باستخدام S من خلال نشر S باستخدام start_index_map. وبشكل أدق:

    1. Sin[start_index_map[k]] = S[k] إذا كان k < start_index_map.size.

    2. Sin[_] = 0 بخلاف ذلك.

  3. أنشئ مؤشرًا Oin في operand من خلال توزيع المؤشرات في سمات البادئة في Out وفقًا لمجموعة collapsed_slice_dims. وبشكل أدق:

    1. Oin[remapped_offset_dims(k)] = Out[offset_dims[k]] إذا كان k < offset_dims.size (يتم تعريف remapped_offset_dims أدناه).

    2. Oin[_] = 0 بخلاف ذلك.

  4. In هو Oin + Sin حيث يشير الرمز + إلى عملية جمع العناصر.

دالة remapped_offset_dims هي دالة أحادية الاتجاه ونطاقها هو [0، offset_dims.size) ونطاقها هو [0، operand.rank) \ collapsed_slice_dims. على سبيل المثال، offset_dims.size هو 4، وoperand.rank هو 6، collapsed_slice_dims هو {0، 2}، ثم remapped_offset_dims هو {01، 13، 24، 35}.

إذا تم ضبط indices_are_sorted على true، يمكن أن تفترض XLA أنّه تم ترتيب start_indices (بترتيب تصاعدي، بعد بعثرة قيمها وفقًا لجدول start_index_map) من قِبل المستخدم. وإذا لم يكن الأمر كذلك، تكون الدلالات محددة التنفيذ.

وصف غير رسمي وأمثلة

بشكل غير رسمي، يتطابق كل فهرس Out في صفيف الإخراج مع عنصر E في صفيف الم Operand، ويتم احتسابه على النحو التالي:

  • نستخدم سمات الحِزم في Out للبحث عن فهرس بداية من start_indices.

  • نستخدم start_index_map لربط الفهرس الأوّلي (الذي قد يكون حجمه أقل من operand.rank) بفهرس أوّلي "كامل" في operand.

  • نقطع شريحة ديناميكية بحجم slice_sizes باستخدام فهرس البدء الكامل.

  • نعيد تشكيل الشريحة من خلال تصغير سمات collapsed_slice_dims. وبما أنّه يجب أن يكون حدّ جميع سمات الشريحة المُدمجة هو 1، فإنّ عملية إعادة التنسيق هذه تكون قانونية دائمًا.

  • نستخدم سمات البدء في Out للفهرسة في هذا المقطع للحصول على عنصر الإدخال، E، المقابل لفهرس الإخراج Out.

تم ضبط index_vector_dim على start_indices.rank - 1 في جميع الأمثلة التالية. لا تؤدي القيم الأكثر إثارة للاهتمام لـ index_vector_dim إلى تغيير العملية بشكل أساسي، ولكنّها تجعل العرض المرئي أكثر تعقيدًا.

للحصول على فكرة عن كيفية ملاءمة كل ما سبق معًا، لنلقِ نظرة على مثال يجمع 5 شرائح من الشكل [8,6] من صفيف [16,11]. يمكن تمثيل موضع شريحة في مصفوفة [16,11] على أنّه فهرس متجه على شكل S64[2]، وبالتالي يمكن تمثيل مجموعة المواضع الخمسة على أنّها مصفوفة S64[5,2].

يمكن بعد ذلك تصوير سلوك عملية التجميع على أنّه تحويل فهرس يأخذ [G,O0,O1]، وهو فهرس في شكل الإخراج، ويربطه بعنصر في صفيف الإدخال بالطريقة التالية:

نختار أولاً متجهًا (X,Y) من مصفوفة فهرس التجميع باستخدام G. العنصر في مصفوفة الإخراج عند الفهرس [G,O0,O1] هو العنصر في مصفوفة الإدخال عند الفهرس [X+O0,Y+O1].

slice_sizes هي [8,6]، وهي تحدّد نطاق O0 و O1، وهذا بدوره يحدّد حدود الشريحة.

تعمل عملية التجميع هذه كشريحة ديناميكية للمجموعة مع G بصفتها سمة المجموعة.

قد تكون مؤشرات التجميع متعددة الأبعاد. على سبيل المثال، سأعرض إليك نسخة أكثر عمومية من المثال أعلاه باستخدام صفيف "جمع الفهارس" بالشكل [4,5,2] ، وسأترجم الفهارس على النحو التالي:

مرة أخرى، يعمل هذا كشريحة ديناميكية للمجموعة G0 و G1 كسمات المجموعة. لا يزال حجم الشريحة [8,6].

تعمل عملية التجميع في XLA على تعميم الدلالات غير الرسمية الموضّحة أعلاه بالطرق التالية:

  1. يمكننا ضبط السمات التي تشكّل سمات offset في شكل الإخراج (السمات التي تحتوي على O0 وO1 في المثال السابق). يتمّ تعريف سمات حِزم الإخراج (السمات التي تحتوي على G0 وG1 في المثال الأخير) على أنّها سمات الإخراج التي ليست سمات تمكين.

  2. قد يكون عدد سمات الإزاحة الناتجة الظاهرة بشكل صريح في شكل المخرج أصغر من عدد السمات في الإدخال. يجب أن يكون حجم القطعة المتعلّقة بهذه الأبعاد "المفقودة" collapsed_slice_dims، والتي تم إدراجها صراحةً على أنّها collapsed_slice_dims.1 وبما أنّ حجم الشريحة هو 1، فإنّ الفهرس الوحيد الصالح لها هو 0، ولا يؤدي حذفها إلى حدوث التباس.

  3. قد تحتوي الشريحة المستخرَجة من صفيف "جمع الفهارس" ((X, Y) في المثال المتأخر) على عناصر أقل من عدد السمات في صفيف الإدخال، ويحدِّد الربط الصريح كيفية توسيع الفهرس للحصول على العدد نفسه من السمات مثل الإدخال.

في المثال الأخير، نستخدم (2) و (3) لتنفيذ tf.gather_nd:

يتم استخدام G0 وG1 لقطع فهرس بدء من صفيف فهارس التجميع كالمعتاد، باستثناء أنّ الفهرس البدءي يحتوي على عنصر واحد فقط، وهو X. وبالمثل، هناك فهرس واحد فقط لموضع الإزاحة في الإخراج بالقيمة O0. ومع ذلك، قبل استخدامها كفهارس في صفيف الإدخال، تتم توسيعها وفقًا لعملية "ربط فهرس التجميع" (start_index_map في الوصف الرسمي) وعملية "ربط البادئة" (remapped_offset_dims في الوصف الرسمي) إلى [X،0] و[0،O0] على التوالي، مما يؤدي إلى [X،O0]. بعبارة أخرى، يتم ربط فهرس الإخراج [G0،G1،O0] بفهرس الإدخال [GatherIndices[G0،G1،0O0] الذي يمنحنا الدلالات الخاصة بـ tf.gather_nd.

رقم slice_sizes لهذا الطلب هو [1,11]. يعني هذا بشكلٍ بديهي أنّ كل X فهرس في صفيف فهارس التجميع يختار صفًا كاملاً، والنتيجة هي التسلسل التلقائي لكل هذه الصفوف.

GetDimensionSize

يمكنك الاطّلاع أيضًا على XlaBuilder::GetDimensionSize.

لعرض حجم السمة المحدّدة للمَعلمة. يجب أن يكون المُعامل على شكل صفيف.

GetDimensionSize(operand, dimension)

الوسيطات النوع الدلالات
operand XlaOp مصفوفة إدخال من n سمة
dimension int64 قيمة في الفاصل [0, n) تحدّد السمة

SetDimensionSize

يمكنك الاطّلاع أيضًا على XlaBuilder::SetDimensionSize.

تُستخدَم لضبط الحجم الديناميكي لسمة XlaOp المحدّدة. يجب أن يكون المُعامل على شكل صفيف.

SetDimensionSize(operand, size, dimension)

الوسيطات النوع الدلالات
operand XlaOp صفيف إدخال من n سمة
size XlaOp int32 يمثّل الحجم الديناميكي أثناء التشغيل
dimension int64 قيمة في النطاق [0, n) تحدّد السمة

تمرير الم Operand كنتيجة، مع السمة الديناميكية التي يتتبّعها compilador

سيتم تجاهل القيم المُضافة من خلال عمليات التخفيض في مرحلة ما بعد المعالجة.

let v: f32[10] = f32[10]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
let five: s32 = 5;
let six: s32 = 6;

// Setting dynamic dimension size doesn't change the upper bound of the static
// shape.
let padded_v_five: f32[10] = set_dimension_size(v, five, /*dimension=*/0);
let padded_v_six: f32[10] = set_dimension_size(v, six, /*dimension=*/0);

// sum == 1 + 2 + 3 + 4 + 5
let sum:f32[] = reduce_sum(padded_v_five);
// product == 1 * 2 * 3 * 4 * 5
let product:f32[] = reduce_product(padded_v_five);

// Changing padding size will yield different result.
// sum == 1 + 2 + 3 + 4 + 5 + 6
let sum:f32[] = reduce_sum(padded_v_six);

GetTupleElement

يمكنك الاطّلاع أيضًا على XlaBuilder::GetTupleElement.

الفهرس في مجموعة تحتوي على قيمة ثابتة في وقت الترجمة

يجب أن تكون القيمة ثابتة في وقت الترجمة حتى تتمكّن عملية استنتاج الشكل من تحديد نوع القيمة الناتجة.

وهذا مشابه لـ std::get<int N>(t) في C++. من الناحية النظرية:

let v: f32[10] = f32[10]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
let s: s32 = 5;
let t: (f32[10], s32) = tuple(v, s);
let element_1: s32 = gettupleelement(t, 1);  // Inferred shape matches s32.

يمكنك أيضًا الاطّلاع على tf.tuple.

الخلاصة

يمكنك الاطّلاع أيضًا على XlaBuilder::Infeed.

Infeed(shape)

الوسيطة النوع الدلالات
shape Shape شكل البيانات المقروءة من واجهة الخلاصة يجب ضبط حقل تنسيق الشكل ليطابق تنسيق البيانات المُرسَلة إلى الجهاز، وإلا سيكون سلوكه غير محدّد.

تقرأ عنصر بيانات واحدًا من واجهة البث التلقائي للإعلانات في الخلاصة في الجهاز، وتُفسر البيانات على أنّها الشكل المحدّد وتنسيقه، وتُعرِض XlaOp للبيانات. يُسمح بعمليات "إدخال الخلاصة" المتعدّدة في عملية حسابية، ولكن يجب أن يكون هناك ترتيب إجمالي بين عمليات "إدخال الخلاصة". على سبيل المثال، يتضمّن اثنان من خلاصتَي الأخبار في الرمز البرمجي أدناه طلبًا إجماليًا لأنّ هناك تبعية بين حلقات while.

result1 = while (condition, init = init_value) {
  Infeed(shape)
}

result2 = while (condition, init = result1) {
  Infeed(shape)
}

لا تتوفّر أشكال المجموعات المُدمَجة. بالنسبة إلى شكل مجموعة ثنائية فارغة، تكون عملية "الخلاصة" غير مجدية بشكلٍ فعال وتستمر بدون قراءة أي بيانات من الخلاصة للجهاز.

أمواج هادئة قصيرة

يمكنك الاطّلاع أيضًا على XlaBuilder::Iota.

Iota(shape, iota_dimension)

ينشئ قيمة ثابتة على الجهاز بدلاً من نقل مضيف كبير محتمل. تنشئ صفيفًا له شكل محدّد ويحتوي على قيم تبدأ من صفر وتزيد بمقدار واحد على طول السمة المحدّدة. بالنسبة إلى أنواع الأرقام العشرية، يكون الصفيف الناتج مساويًا لـ ConvertElementType(Iota(...)) حيث يكون Iota من النوع الصحيح ويتم التحويل إلى النوع العشري.

الوسيطات النوع الدلالات
shape Shape شكل الصفيف الذي أنشأه Iota()
iota_dimension int64 السمة المطلوب زيادتها.

على سبيل المثال، يعرض Iota(s32[4, 8], 0)

  [[0, 0, 0, 0, 0, 0, 0, 0 ],
   [1, 1, 1, 1, 1, 1, 1, 1 ],
   [2, 2, 2, 2, 2, 2, 2, 2 ],
   [3, 3, 3, 3, 3, 3, 3, 3 ]]

يمكن إرجاع المشتريات مقابل Iota(s32[4, 8], 1).

  [[0, 1, 2, 3, 4, 5, 6, 7 ],
   [0, 1, 2, 3, 4, 5, 6, 7 ],
   [0, 1, 2, 3, 4, 5, 6, 7 ],
   [0, 1, 2, 3, 4, 5, 6, 7 ]]

خريطة

يمكنك الاطّلاع أيضًا على XlaBuilder::Map.

Map(operands..., computation)

الوسيطات النوع الدلالات
operands تسلسل N XlaOp مصفوفات N من الأنواع T0..T{N-1}
computation XlaComputation حساب من النوع T_0, T_1, .., T_{N + M -1} -> S مع N مَعلمة من النوع T وM من نوع عشوائي
dimensions صفيف int64 صفيف لسمات الخريطة

تطبِّق دالة عددية على صفائف operands المحدّدة، ما ينتج عنه صفيف بالأبعاد نفسها حيث يكون كل عنصر هو نتيجة الدالة المُحدَّدة المطبَّقة على العناصر المقابلة في صفائف الإدخال.

الدالة المُعرَّفة هي عملية حسابية عشوائية مع القيود التي تفرضها N مدخلات من النوع السقلي T وإخراج واحد من النوع S. يحتوي الناتج على السمات نفسها التي تحتوي عليها المعاملات باستثناء أنّه يتم استبدال نوع العنصر T بـ S.

على سبيل المثال: تربط Map(op1, op2, op3, computation, par1) elem_out <- computation(elem1, elem2, elem3, par1) في كل فهرس (متعدّد الأبعاد) في صفائف الإدخال لإنشاء صفيف الإخراج.

OptimizationBarrier

يمنع أي عملية تحسين من نقل العمليات الحسابية عبر الحاجز.

يضمن تقييم جميع المدخلات قبل أيّ عوامل تشغيل تعتمد على مخرجات الحاجز.

وسادة

يمكنك الاطّلاع أيضًا على XlaBuilder::Pad.

Pad(operand, padding_value, padding_config)

الوسيطات النوع الدلالات
operand XlaOp مصفوفة من النوع T
padding_value XlaOp عدد صحيح من النوع T لملء الحشو المُضاف
padding_config PaddingConfig مقدار المساحة الفارغة على كلا الحافتَين (منخفض أو مرتفع) وبين عناصر كل سمة

يوسع صفيف operand المحدَّد عن طريق إضافة مسافة حول الصفيف وكذلك بين عناصر الصفيف باستخدام padding_value المحدَّد. padding_config تُحدِّد مقدار الحشو على الحواف والحشو الداخلي لكل سمة.

PaddingConfig هو حقل متكرّر من PaddingConfigDimension، يحتوي على ثلاثة حقول لكل سمة: edge_padding_low وedge_padding_high و interior_padding.

تحدِّد edge_padding_low وedge_padding_high مقدار الحشو المُضاف في الطرف الأدنى (بجانب الفهرس 0) والطرف الأعلى (بجانب أعلى فهرس) لكل سمة على التوالي. يمكن أن تكون قيمة الحشو على الحواف سالبة، ويشير القيمة المطلقة للحشو السالب إلى عدد العناصر التي يجب إزالتها من السمة المحدّدة.

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

لا تؤدي هذه العملية إلى أيّ تغيير إذا كانت جميع أزواج الحشو على الحواف هي (0، 0) وكانت قيم الحشو الداخلي هي 0. يعرض الشكل أدناه أمثلة على قيم edge_padding وinterior_padding المختلفة لصفيف ثنائي الأبعاد.

Recv

يمكنك الاطّلاع أيضًا على XlaBuilder::Recv.

Recv(shape, channel_handle)

الوسيطات النوع الدلالات
shape Shape شكل البيانات المطلوب استلامها
channel_handle ChannelHandle معرّف فريد لكل زوج من الإرسال/الاستلام

تتلقّى بيانات بالشكل المحدّد من تعليمات Send في عملية حسابية أخرى تشترك في الاسم المعرِّف نفسه للقناة. تعرِض هذه الدالة رمز معالجة XlaOp للبيانات المستلَمة.

تمثّل واجهة برمجة التطبيقات للعميل في عملية Recv الاتّصال المتزامن. ومع ذلك، يتم تجزئة التعليمات داخليًا إلى تعليمات HLO (Recv وRecvDone) لتفعيل عمليات نقل البيانات غير المتزامنة. يمكنك أيضًا الاطّلاع على HloInstruction::CreateRecv وHloInstruction::CreateRecvDone.

Recv(const Shape& shape, int64 channel_id)

تخصيص الموارد المطلوبة لتلقّي البيانات من تعليمات Send التي تحتوي على معرّف القناة نفسه تُعيد هذه الدالة سياقًا للموارد المخصّصة، والتي يتم استخدامها من خلال تعليمات RecvDone التالية للانتظار إلى أن تكتمل عملية نقل data. السياق هو مجموعة من {receive buffer (shape), request identifier (U32)} ولا يمكن استخدامه إلا من خلال تعليمات RecvDone.

RecvDone(HloInstruction context)

استنادًا إلى سياق تم إنشاؤه بواسطة تعليمات Recv، ينتظر اكتمال نقل البيانات ويعرض البيانات التي تم استلامها.

تقليل

يمكنك الاطّلاع أيضًا على XlaBuilder::Reduce.

تُطبِّق دالة تقليل على صفيف واحد أو أكثر بشكل موازٍ.

Reduce(operands..., init_values..., computation, dimensions)

الوسيطات النوع الدلالات
operands تسلسل N XlaOp مصفوفات N من أنواع T_0, ..., T_{N-1}
init_values تسلسل N XlaOp عدد N من القيم السلاسل من أنواع T_0, ..., T_{N-1}.
computation XlaComputation عملية حسابية من النوع T_0, ..., T_{N-1}, T_0, ..., T_{N-1} -> Collate(T_0, ..., T_{N-1})
dimensions صفيف int64 صفيف غير مرتب للسمات المطلوب تقليلها

المكان:

  • يجب أن تكون قيمة N أكبر من أو تساوي 1.
  • يجب أن يكون الحساب "تقريبًا" ترابطيًا (راجِع المعلومات أدناه).
  • يجب أن تتطابق أبعاد جميع صفائف الإدخال.
  • يجب أن تشكل جميع القيم الأولية هوية ضمن computation.
  • إذا كان N = 1، Collate(T) هو T.
  • إذا كان N > 1، Collate(T_0, ..., T_{N-1}) عبارة عن مجموعة من عناصر N من النوع T.

تقلِّل هذه العملية سمة واحدة أو أكثر من كل صفيف إدخال إلى مقاييس. عدد سمات كل صفيف معروض هو number_of_dimensions(operand) - len(dimensions). ناتج العملية هو Collate(Q_0, ..., Q_N) حيث Q_i صفيف من النوع T_i، وتكون أبعاده موضّحة أدناه.

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

أمثلة

عند التقليل على مستوى سمة واحدة في صفيف واحد من صف واحد يحتوي على القيم [10, 11, 12, 13]، باستخدام دالة التقليل f (وهي computation)، يمكن حساب ذلك على النحو التالي:

f(10, f(11, f(12, f(init_value, 13)))

ولكن هناك أيضًا العديد من الاحتمالات الأخرى، مثل:

f(init_value, f(f(10, f(init_value, 11)), f(f(init_value, 12), f(init_value, 13))))

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

result_shape <- remove all dims in dimensions from operand_shape

# Iterate over all elements in result_shape. The number of r's here is equal
# to the number of dimensions of the result.
for r0 in range(result_shape[0]), r1 in range(result_shape[1]), ...:
  # Initialize this result element
  result[r0, r1...] <- 0

  # Iterate over all the reduction dimensions
  for d0 in range(dimensions[0]), d1 in range(dimensions[1]), ...:
    # Increment the result element with the value of the operand's element.
    # The index of the operand's element is constructed from all ri's and di's
    # in the right order (by construction ri's and di's together index over the
    # whole operand shape).
    result[r0, r1...] += operand[ri... di]

في ما يلي مثال على تقليل صفيف ثنائي الأبعاد (مصفوفة). يحتوي الشكل على بُعدَين، البُعد 0 بحجم 2 والبُعد 1 بحجم 3:

نتائج تقليل السمتَين 0 أو 1 باستخدام دالة "إضافة":

يُرجى العلم أنّ كلتا نتيجتَي الاختزال هما صفيفَان أحاديَا الأبعاد. يعرض المخطّط البياني أحدهما كعمود والآخر كصف فقط لتسهيل الرؤية.

للحصول على مثال أكثر تعقيدًا، إليك صفيف ثلاثي الأبعاد. عدد أبعادها هو 3، ويتمثل البُعد 0 في الحجم 4، والبُعد 1 في الحجم 2، والبُعد 2 في الحجم 3. للتبسيط، تتمّ تكرار القيم من 1 إلى 6 في السمة 0.

على غرار المثال ثنائي الأبعاد، يمكننا تقليل سمة واحدة فقط. إذا قلّلنا السمة 0، على سبيل المثال، نحصل على صفيف ثنائي الأبعاد تم تجميع جميع القيم في السمة 0 في قيمة عددية:

|  4   8  12 |
| 16  20  24 |

إذا قلّلنا السمة 2، نحصل أيضًا على صفيف ثنائي الأبعاد تم تجميع كل القيم في السمة 2 في قيمة عددية:

| 6  15 |
| 6  15 |
| 6  15 |
| 6  15 |

يُرجى العِلم أنّه يتم الحفاظ على الترتيب النسبي بين السمات المتبقية في الإدخال في الإخراج، ولكن قد يتم تخصيص أرقام جديدة لبعض السمات (لأنّه يتغيّر عدد السمات).

يمكننا أيضًا تقليل الأبعاد المتعددة. تؤدي إضافة السمتَين 0 و1 إلى تقليل القيمة، ما ينتج عنه صفيف 1D‏ [20, 28, 36].

يؤدي تقليل الصفيف الثلاثي الأبعاد على جميع أبعاده إلى إنشاء المقياس 84.

دالة Reduce المتعدّدة المَعلمات

عندما يكون N > 1، يكون تطبيق دالة reduce أكثر تعقيدًا قليلاً، لأنّه يتم تطبيقه في الوقت نفسه على جميع المدخلات. يتم تقديم المَعلمات إلى عملية ال حساب بالترتيب التالي:

  • تنفيذ قيمة مخفضة للمعامل الأول
  • ...
  • تشغيل قيمة مخفضة للمعامل N
  • إدخال قيمة للم Operand الأول
  • ...
  • إدخال قيمة للمَعلمة N

على سبيل المثال، نأخذ في الاعتبار دالة الاختزال التالية التي يمكن استخدامها للقيام بحساب الحد الأقصى وargmax لصفيف أحادي الأبعاد بشكل موازٍ:

f: (Float, Int, Float, Int) -> Float, Int
f(max, argmax, value, index):
  if value >= max:
    return (value, index)
  else:
    return (max, argmax)

بالنسبة إلى صفائف الإدخال V = Float[N], K = Int[N] ذي الأبعاد الواحدة وقيم البدء I_V = Float, I_K = Int، فإنّ النتيجة f_(N-1) الناتجة عن التقليل على مستوى سمة الإدخال الوحيدة هي ما يعادل التطبيق المتكرّر التالي:

f_0 = f(I_V, I_K, V_0, K_0)
f_1 = f(f_0.first, f_0.second, V_1, K_1)
...
f_(N-1) = f(f_(N-2).first, f_(N-2).second, V_(N-1), K_(N-1))

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

ReducePrecision

يمكنك الاطّلاع أيضًا على XlaBuilder::ReducePrecision.

يحدِّد تأثير تحويل قيم النقطة العائمة إلى تنسيق بدقة أقل (مثل IEEE-FP16) والعودة إلى التنسيق الأصلي. يمكن تحديد عدد وبتَي القاعدة والأس في التنسيق الأقل دقة بشكلٍ عشوائي، على الرغم من أنّه قد لا تكون جميع أحجام البتات متوافقة مع جميع عمليات تنفيذ الأجهزة.

ReducePrecision(operand, mantissa_bits, exponent_bits)

الوسيطات النوع الدلالات
operand XlaOp مصفوفة من النوع النقطة العائمة T
exponent_bits int32 عدد بتات الأس في تنسيق بدقة أقل
mantissa_bits int32 عدد بتات الكسور العشرية بتنسيق دقة أقل

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

يجب أن يتضمّن التنسيق الأقل دقة رمزًا واحدًا على الأقل للقوة (لتمييز قيمة الصفر عن القيمة اللانهائية، لأنّ كلاهما يتضمّن مانتيساً تساوي صفرًا)، ويجب أن يتضمّن عددًا غير سالب من وحدات المانتيسا. قد يتجاوز عدد بتات الأس أو الجزء العشري القيمة المقابلة للنوع T، ويكون الجزء المناظر من عملية التحويل مجرد عملية لا تؤدي إلى أيّ نتيجة.

ReduceScatter

يمكنك الاطّلاع أيضًا على XlaBuilder::ReduceScatter.

ReduceScatter هي عملية جماعية تُجري بشكل فعّال عملية AllReduce ثم تُوزّع النتيجة من خلال تقسيمها إلى shard_count كتل على طول scatter_dimension وتتلقّى النسخة المكرّرة i في مجموعة النُسخ المكرّرة شريحة ith.

ReduceScatter(operand, computation, scatter_dim, shard_count, replica_group_ids, channel_id)

الوسيطات النوع الدلالات
operand XlaOp صفيف أو مجموعة غير فارغة من الصفائف لتقليلها على مستوى النُسخ المكرّرة
computation XlaComputation احتساب التخفيض
scatter_dimension int64 السمة المطلوب بعثرها
shard_count int64 عدد المجموعات المطلوب تقسيمها scatter_dimension
replica_groups متّجه المتّجهات int64 المجموعات التي يتم إجراء التخفيضات بينها
channel_id اختياري int64 معرّف قناة اختياري للتواصل بين الوحدات
  • عندما تكون operand صفيفًا من الصفائف، يتم تنفيذ عملية التجميع-التوزيع على كل عنصر من الصفيف.
  • replica_groups هي قائمة بمجموعات النُسخ التي يتم التقليل بينها (يمكن استرداد معرّف النسخة الحالية باستخدام ReplicaId). يحدّد ترتيب النُسخ في كل مجموعة الترتيب الذي سيتم فيه توزيع نتيجة التقليل الشامل. يجب أن يكون الحقل replica_groups فارغًا (وفي هذه الحالة تنتمي جميع النُسخ المكرّرة إلى مجموعة واحدة)، أو أن يحتوي على عدد العناصر نفسه لعدد النُسخ المكرّرة. عندما يكون هناك أكثر من مجموعة نُسخ طبق الأصل واحدة، يجب أن تكون جميعها بالحجم نفسه. على سبيل المثال، يُجري replica_groups = {0, 2}, {1, 3} عملية تقليل بين النسخ المكرّرة 0 و2 و1 و3، ثم ينشر النتيجة.
  • shard_count هو حجم كل مجموعة نُسخ. نحتاج إلى ذلك في الحالات التي تكون فيها قيمة الحقل replica_groups فارغة. إذا لم تكن replica_groups فارغة، يجب أن تساوي shard_count حجم كل مجموعة نُسخ طبق الأصل.
  • يتم استخدام channel_id للتواصل بين الوحدات: لا يمكن إلا reduce-scatter للعمليات التي تحمل channel_id نفسه التواصل مع بعضها.

شكل الإخراج هو شكل الإدخال الذي تم جعله أصغر scatter_dimension shard_count مرة. على سبيل المثال، إذا كانت هناك نسختان طبق الأصل وكان الم Operand يحمل القيمة [1.0, 2.25] و[3.0, 5.25] على التوالي في نسختَي النسخ، ستكون قيمة الإخراج من هذا الإجراء الذي يكون فيه scatter_dim هو 0 هي [4.0] للنسخة الأولى و[7.5] للنسخة الثانية.

ReduceWindow

يمكنك الاطّلاع أيضًا على XlaBuilder::ReduceWindow.

تطبِّق دالة تقليل على جميع العناصر في كل نافذة من تسلسل N مصفوفات متعددة الأبعاد، ما يؤدي إلى إنشاء صفيف واحد أو مجموعة من N مصفوفات متعددة الأبعاد كإخراج. تحتوي كل صفيف إخراج على عدد العناصر نفسه المُمثّل لعدد المواضع الصالحة للنافذة. يمكن التعبير عن طبقة التجميع على النحو التالي: ReduceWindow. على غرار Reduce، يتم دائمًا تطبيق computation بعد init_values على يمين الصفحة.

ReduceWindow(operands..., init_values..., computation, window_dimensions, window_strides, padding)

الوسيطات النوع الدلالات
operands N XlaOps تسلسل من صفائف متعددة الأبعاد من النوع T_0,..., T_{N-1} بعدد N، يمثّل كلّ منها المنطقة الأساسية التي يتمّ وضع النافذة عليها
init_values N XlaOps القيم البادئة N للاختزال، واحدة لكل مَعلمة من المَعلمات N راجِع تقليل لمعرفة التفاصيل.
computation XlaComputation دالة تقليل من النوع T_0, ..., T_{N-1}, T_0, ..., T_{N-1} -> Collate(T_0, ..., T_{N-1})، لتطبيقها على العناصر في كل نافذة من جميع عناصر الإدخال
window_dimensions ArraySlice<int64> صفيف من الأعداد الصحيحة لقيم سمة الفترة
window_strides ArraySlice<int64> صفيف من الأعداد الصحيحة لقيم خطوة النافذة
base_dilations ArraySlice<int64> صفيف من الأعداد الصحيحة لقيم التمدد الأساسية
window_dilations ArraySlice<int64> صفيف من الأعداد الصحيحة لقيم تمديد النافذة
padding Padding نوع الحشو للنافذة (Padding::kSame، الذي يضيف الحشو للحصول على شكل الإخراج نفسه مثل الإدخال إذا كانت الخطوة 1، أو Padding::kValid، الذي لا يستخدم أيّ حشو و "يوقف" النافذة بعد أن تصبح غير مناسبة)

المكان:

  • يجب أن تكون قيمة N أكبر من أو تساوي 1.
  • يجب أن تتطابق أبعاد جميع صفائف الإدخال.
  • إذا كان N = 1، Collate(T) هو T.
  • إذا كان N > 1، Collate(T_0, ..., T_{N-1}) عبارة عن مجموعة من عناصر N من النوع (T0,...T{N-1}).

يوضّح الرمز والشكل أدناه مثالاً على استخدام ReduceWindow. الإدخال هو مصفوفة بحجم [4x6] وكل من سمات window_dimensions وwindow_stride_dimensions هي [2x3].

// Create a computation for the reduction (maximum).
XlaComputation max;
{
  XlaBuilder builder(client_, "max");
  auto y = builder.Parameter(0, ShapeUtil::MakeShape(F32, {}), "y");
  auto x = builder.Parameter(1, ShapeUtil::MakeShape(F32, {}), "x");
  builder.Max(y, x);
  max = builder.Build().value();
}

// Create a ReduceWindow computation with the max reduction computation.
XlaBuilder builder(client_, "reduce_window_2x3");
auto shape = ShapeUtil::MakeShape(F32, {4, 6});
auto input = builder.Parameter(0, shape, "input");
builder.ReduceWindow(
    input,
    /*init_val=*/builder.ConstantLiteral(LiteralUtil::MinValue(F32)),
    *max,
    /*window_dimensions=*/{2, 3},
    /*window_stride_dimensions=*/{2, 3},
    Padding::kValid);

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

للحصول على مثال على الحشو غير البسيط، ننصحك بحساب الحد الأدنى لإطار التقليل (القيمة الأولية هي MAX_FLOAT) باستخدام السمة 3 وخطوة التقدّم 2 على مصفوفة الإدخال [10000, 1000, 100, 10, 1]. تعمل دالة الحشو kValid على احتساب الحد الأدنى على مدار فترتين صالحتَين: [10000, 1000, 100] و[100, 10, 1]، ما يؤدي إلى الناتج [100, 1]. تعمل دالة الحشو kSame أولاً على إضافة عناصر إلى الصفيف لكي يكون الشكل بعد نافذة الاختزال مماثلًا للإدخال في الخطوة الأولى من خلال إضافة عناصر أولية على كلا الجانبين، ما يؤدي إلى الحصول على [MAX_VALUE, 10000, 1000, 100, 10, 1, MAX_VALUE]. يؤدي تشغيل دالة reduce-window على الصفيف المُضاف إليه محتوى إلى العمل على ثلاث نوافذ [MAX_VALUE, 10000, 1000] و[1000, 100, 10] و[10, 1, MAX_VALUE]، ويؤدي إلى توليد[1000, 10, 1].

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

ReplicaId

يمكنك الاطّلاع أيضًا على XlaBuilder::ReplicaId.

تُعيد هذه الدالة المعرّف الفريد (عدد صحيح 32 بت) للنسخة.

ReplicaId()

المعرّف الفريد لكل نسخة هو عدد صحيح غير موقَّع في النطاق [0, N)، حيث يكون N هو عدد النُسخ. بما أنّ جميع النُسخ المكرّرة تعمل بالبرنامج نفسه، سيؤدي استدعاء ReplicaId() في البرنامج إلى عرض قيمة مختلفة في كل نسخة مكرّرة.

إعادة التشكيل

راجِع أيضًا XlaBuilder::Reshape وعملية Collapse.

تعيد تشكيل سمات صفيف إلى تكوين جديد.

Reshape(operand, dimensions)

الوسيطات النوع الدلالات
operand XlaOp صفيف من النوع T
dimensions int64 متّجه متجه أحجام السمات الجديدة

من الناحية النظرية، تعمل دالة reshape أولاً على تسطيح صفيف إلى متجه أحادي الأبعاد من قيم البيانات، ثمّ تنقّي هذا المتجه إلى شكل جديد. تشكل وسيطات الإدخال مصفوفة عشوائية من النوع T، وناقلاً ثابتًا في وقت الترجمة لعناصر فهرس السمات، وناقلاً ثابتًا في وقت الترجمة لحجم السمات للنتيجة. يحدِّد متجه dimensions حجم مصفوفة الإخراج. القيمة في الفهرس 0 في dimensions هي حجم السمة 0، والقيمة في الفهرس 1 هي حجم السمة 1، وهكذا. يجب أن يساوي حاصل ضرب سمات dimensions حاصل ضرب أحجام سمات الم Operand. عند تحسين المصفوفة المُدمَجة إلى المصفوفة متعددة الأبعاد التي تحدّدها dimensions، يتم ترتيب السمات في dimensions من الأكثر اختلافًا ببطء (الأكثر أهمية) إلى الأكثر اختلافًا بسرعه (الأكثر ثانوية).

على سبيل المثال، لنفترض أنّ v هي مصفوفة من 24 عنصرًا:

let v = f32[4x2x3] { { {10, 11, 12}, {15, 16, 17} },
                    { {20, 21, 22}, {25, 26, 27} },
                    { {30, 31, 32}, {35, 36, 37} },
                    { {40, 41, 42}, {45, 46, 47} } };

let v012_24 = Reshape(v, {24});
then v012_24 == f32[24] {10, 11, 12, 15, 16, 17, 20, 21, 22, 25, 26, 27,
                         30, 31, 32, 35, 36, 37, 40, 41, 42, 45, 46, 47};

let v012_83 = Reshape(v, {8,3});
then v012_83 == f32[8x3] { {10, 11, 12}, {15, 16, 17},
                          {20, 21, 22}, {25, 26, 27},
                          {30, 31, 32}, {35, 36, 37},
                          {40, 41, 42}, {45, 46, 47} };

كحالة خاصة، يمكن أن تحوِّل الدالة reshape صفيفًا يتألّف من عنصر واحد إلى عدد سكالري، والعكس صحيح. على سبيل المثال:

Reshape(f32[1x1] { {5} }, {}) == 5;
Reshape(5, {1,1}) == f32[1x1] { {5} };

Rev (عكس)

يمكنك الاطّلاع أيضًا على XlaBuilder::Rev.

Rev(operand, dimensions)

الوسيطات النوع الدلالات
operand XlaOp صفيف من النوع T
dimensions ArraySlice<int64> السمات المطلوب عكسها

تعكس ترتيب العناصر في صفيف operand على طول dimensions المحدّد، ما يؤدي إلى إنشاء صفيف ناتج بالشكل نفسه. يتم تخزين كل عنصر من ملف صفيف المعاملات في فهرس متعدد الأبعاد في صفيف الإخراج في ملف فهرس محوَّل. يتم تحويل المؤشر المتعدّد الأبعاد عن طريق عكس المؤشر في كلّ سمة تريد عكسها (أي إذا كانت سمة بحجم N هي إحدى السمات التي تريد عكسها، يتم تحويل مؤشرها i إلى N - 1 - i).

من بين استخدامات عملية Rev عكس صفيف أوزان التفاف على طول سمتَي النافذة أثناء احتساب التدرّج في الشبكات العصبية.

RngNormal

يمكنك الاطّلاع أيضًا على XlaBuilder::RngNormal.

تُنشئ دالة RANDALL ناتجًا بشكل معيّن باستخدام أرقام عشوائية يتم إنشاؤها وفقًا للتوزيع \(N(\mu, \sigma)\) العادي. يجب أن يكون للمَعلمتَين \(\mu\) و \(\sigma\)و شكل الإخراج نوع عنصر فاصلة عائمة. بالإضافة إلى ذلك، يجب أن تكون المَعلمات ذات قيمة عددية.

RngNormal(mu, sigma, shape)

الوسيطات النوع الدلالات
mu XlaOp عدد скалري من النوع T يحدِّد متوسّط الأرقام التي تم إنشاؤها
sigma XlaOp عدد скалري من النوع T يحدِّد الانحراف المعياري للقيمة التي تم إنشاؤها
shape Shape شكل الإخراج من النوع T

RngUniform

يمكنك الاطّلاع أيضًا على XlaBuilder::RngUniform.

تُنشئ هذه الدالة ناتجًا لشكل معيّن باستخدام أرقام عشوائية يتم إنشاؤها باتّباع التوزيع الموحّد على النطاق \([a,b)\). يجب أن تكون المَعلمات ونوع عنصر المخرجات من النوع المنطقي أو النوع الصحيح أو النوع المتغير النقطة العائمة، ويجب أن تكون الأنواع متسقة. لا تتوافق الخلفيات لوحدة المعالجة المركزية ووحدة معالجة الرسومات حاليًا سوى مع F64 وF32 وF16 وBF16 وS64 وU64 وS32 وU32. بالإضافة إلى ذلك، يجب أن تكون المَعلمات ذات قيمة عددية. إذا \(b <= a\) كانت النتيجة محددة من خلال التنفيذ

RngUniform(a, b, shape)

الوسيطات النوع الدلالات
a XlaOp عدد скалري من النوع T يحدِّد الحدّ الأدنى للفاصل
b XlaOp عدد скалري من النوع T يحدِّد الحدّ الأقصى للفاصل
shape Shape شكل الإخراج من النوع T

RngBitGenerator

تُنشئ هذه الدالة إخراجًا بشكل معيّن مملوء بوحدات بت عشوائية موحّدة باستخدام الخوارزمية المحدّدة (أو الإعداد التلقائي للخلفية) وتُرجع حالة معدَّلة (بالشكل نفسه للحالة الأولية) والبيانات العشوائية التي تم إنشاؤها.

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

نضمن أنّ الإخراج هو دالة حتمية للحالة الأولية، ولكنلا نضمن أنّه حتمِي بين الخلفيات وإصدارات compilers المختلفة.

RngBitGenerator(algorithm, key, shape)

الوسيطات النوع الدلالات
algorithm RandomAlgorithm خوارزمية PRNG التي سيتم استخدامها
initial_state XlaOp الحالة الأولية لخوارزمية PRNG
shape Shape شكل الإخراج للبيانات التي تم إنشاؤها

القيم المتاحة لسمة algorithm:

رسم بياني للنقاط المبعثرة

تُنشئ عملية التوزيع في XLA تسلسلًا من النتائج التي هي قيم صفيف الإدخال operands، مع عدّة شرائح (في الفهارس المحدّدة باستخدام scatter_indices) تم تعديلها باستخدام تسلسل القيم في updates باستخدام update_computation.

يمكنك الاطّلاع أيضًا على XlaBuilder::Scatter.

scatter(operands..., scatter_indices, updates..., update_computation, index_vector_dim, update_window_dims, inserted_window_dims, scatter_dims_to_operand_dims)

الوسيطات النوع الدلالات
operands تسلسل N XlaOp مصفوفات N من الأنواع T_0, ..., T_N التي سيتم توزيعها عليها
scatter_indices XlaOp صفيف يحتوي على الفواصل الزمنية لبداية الشرائح التي يجب توزيعها عليها
updates تسلسل N XlaOp مصفوفات N من أنواع T_0, ..., T_N يحتوي updates[i] على القيم التي يجب استخدامها لدالة التشتت operands[i].
update_computation XlaComputation عملية الحساب التي سيتم استخدامها لدمج القيم الحالية في صفيف الإدخال والتعديلات أثناء التوزيع يجب أن تكون هذه العملية الحسابية من النوع T_0, ..., T_N, T_0, ..., T_N -> Collate(T_0, ..., T_N).
index_vector_dim int64 السمة في scatter_indices التي تحتوي على الفهارس الافتتاحية.
update_window_dims ArraySlice<int64> مجموعة الأبعاد في شكل updates التي تشكّل أبعاد النافذة
inserted_window_dims ArraySlice<int64> مجموعة أبعاد النافذة التي يجب إدراجها في شكل updates
scatter_dims_to_operand_dims ArraySlice<int64> خريطة سمات من مؤشرات الانتشار إلى مساحة فهرس الم Operand يتم تفسير هذا الصفيف على أنّه يربط i بـ scatter_dims_to_operand_dims[i] . يجب أن يكون العدد فرديًا وإجماليًا.
indices_are_sorted bool ما إذا كان من المؤكد أن يتم ترتيب الفهارس حسب المُتصل
unique_indices bool ما إذا كان المتصل يضمن أنّ الفهارس فريدة

المكان:

  • يجب أن تكون قيمة N أكبر من أو تساوي 1.
  • يجب أن تتضمّن كلّ من operands[0] و... وoperands[N-1] السمات نفسها.
  • يجب أن تتضمّن كلّ من updates[0] و... وupdates[N-1] السمات نفسها.
  • إذا كان N = 1، Collate(T) هو T.
  • إذا كان N > 1، Collate(T_0, ..., T_N) عبارة عن مجموعة من عناصر N من النوع T.

إذا كانت index_vector_dim تساوي scatter_indices.rank، نفترض ضمنيًا أنّه scatter_indices تحتوي على سمة 1 متأخرة.

نحدِّد update_scatter_dims من النوع ArraySlice<int64> على أنّه مجموعة السمات في شكل updates التي لا تنتمي إلى update_window_dims، بترتيب صعودي.

يجب أن تلتزم وسيطات التوزيع بالقيود التالية:

  • يجب أن تحتوي كل مصفوفة updates على update_window_dims.size + scatter_indices.rank - 1 سمة.

  • يجب أن تتوافق حدود السمة i في كل صفيف updates مع النقاط التالية:

    • إذا كانت i متوفّرة في update_window_dims (أي تساوي update_window_dims[k] لبعض k)، يجب ألا يتجاوز حدّ السمة i في updates الحدّ المقابل لoperand بعد تضمين inserted_window_dims (أي adjusted_window_bounds[k]، حيث يحتوي adjusted_window_bounds على حدود operand مع إزالة الحدود في الفهرس inserted_window_dims).
    • إذا كانت قيمة i متوفّرة في update_scatter_dims (أي تساوي update_scatter_dims[k] لبعض القيمk)، يجب أن يكون حدّ السمة i في updates مساويًا للحدّ المقابل ل scatter_indices، مع تخطّي index_vector_dim (أي scatter_indices.shape.dims[k]، إذا كانت k < index_vector_dim و scatter_indices.shape.dims[k+1] في الحالات الأخرى).
  • يجب أن يكون update_window_dims بترتيب تصاعدي، وألا يتضمّن أي أرقام سمات متكرّرة، وأن يكون ضمن النطاق [0, updates.rank).

  • يجب أن يكون inserted_window_dims بترتيب تصاعدي، وألا يتضمّن أي أرقام سمات متكرّرة، وأن يكون ضمن النطاق [0, operand.rank).

  • يجب أن يساوي operand.rank مجموع update_window_dims.size و inserted_window_dims.size.

  • يجب أن تكون scatter_dims_to_operand_dims.size مساوية scatter_indices.shape.dims[index_vector_dim]، ويجب أن تكون قيمها في النطاق [0, operand.rank).

بالنسبة إلى فهرس معيّن U في كل صفيف updates، يتم احتساب الفهرس المقابل I في صفيف operands المقابل الذي يجب تطبيق هذا التعديل عليه على النحو التالي:

  1. لنفترض أنّ G = { U[k] لـ k في update_scatter_dims }. استخدِم G للبحث عن متجه الفهرس S في صفيف scatter_indices بحيث يكون S[i] = scatter_indices[Combine(G, i)] حيث تُدرج دالة Combine(A, b) العنصر b في المواضع index_vector_dim في A.
  2. أنشئ فهرسًا Sin في operand باستخدام S من خلال نثر S باستخدام خريطة scatter_dims_to_operand_dims. أسلوب أكثر رسمية:
    1. Sin[scatter_dims_to_operand_dims[k]] = S[k] إذا كان k < scatter_dims_to_operand_dims.size.
    2. Sin[_] = 0 بخلاف ذلك.
  3. أنشئ فهرسًا Win في كل صفيف operands من خلال نثر الفهارس في update_window_dims في U وفقًا ل inserted_window_dims. أسلوب أكثر رسمية:
    1. Win[window_dims_to_operand_dims(k)] = U[k] إذا كان k في update_window_dims، حيث window_dims_to_operand_dims هي الوظيفة الأحادية الاتجاه التي لها النطاق [0، update_window_dims.size) والنطاق [0، operand.rank) \ inserted_window_dims. (على سبيل المثال، إذا كان update_window_dims.size هو 4 وoperand.rank هو 6 و inserted_window_dims هو {0، 2}، يكونwindow_dims_to_operand_dims هو {01، 13، 24، 35}).
    2. Win[_] = 0 بخلاف ذلك.
  4. I هو Win + Sin حيث يشير الرمز + إلى عملية جمع العناصر.

باختصار، يمكن تعريف عملية التشتت على النحو التالي.

  • اضبط output على operands، أي لجميع الفهارس J، لجميع الفهارس O في المصفوفة operands[J]:
    output[J][O] = operands[J][O]
  • لكل فهرس U في الصفيف updates[J] والفهرس المقابل O في الصفيف operand[J]، إذا كان O فهرسًا صالحًا لسمة output:
    (output[0][O]، ...، output[N-1][O]) =update_computation(output[0][O]، ...، ،output[N-1][Oupdates[0][U]، ...،updates[N-1][U])

إنّ ترتيب تطبيق التعديلات غير محدّد. وبالتالي، عندما تشير عدة فهرسات في updates إلى الفهرس نفسه في operands، ستكون القيمة المقابلة في output غير محدّدة.

تجدر الإشارة إلى أنّ المَعلمة الأولى التي يتم تمريرها إلى update_computation ستكون دائمًا القيمة الحالية من صفيف output، وستكون المَعلمة الثانية دائمًا القيمة من صفيف updates. وهذا مهم بشكل خاص في الحالات التي تكون فيها update_computation غير تبديلية.

في حال ضبط indices_are_sorted على "صحيح"، يمكن أن تفترض XLA أنّه تم ترتيب scatter_indices (بترتيب تصاعدي، بعد توزيع قيمه وفقًا لـ scatter_dims_to_operand_dims) من قِبل المستخدم. وإذا لم يكن الأمر كذلك، يتم تحديد المعاني من خلال التنفيذ.

إذا تم ضبط unique_indices على true، يمكن أن تفترض XLA أنّ جميع العناصر المُشتَتة هي فريدة. وبالتالي، يمكن أن تستخدم XLA عمليات غير ذرية. إذا تم ضبط قيمة unique_indices على "صحيح" وكانت الفهارس التي يتم توزيعها عليها ليست فريدة، تكون الدلالات محدّدة من التنفيذ.

بشكل غير رسمي، يمكن اعتبار عملية التشتيت عكس عملية التجميع، أي أنّه تُعدّل عملية التشتيت العناصر في الإدخال التي يتم استخراجها من قِبل عملية التجميع المقابلة.

للحصول على وصف غير رسمي مفصّل وأمثلة، يُرجى الرجوع إلى القسم "الوصف غير الرسمي" ضمن Gather.

اختيار

يمكنك الاطّلاع أيضًا على XlaBuilder::Select.

تُنشئ صفيفًا للإخراج من عناصر صفيفَي إدخال استنادًا إلى قيم صفيف العبارة.

Select(pred, on_true, on_false)

الوسيطات النوع الدلالات
pred XlaOp مصفوفة من النوع PRED
on_true XlaOp صفيف من النوع T
on_false XlaOp صفيف من النوع T

يجب أن تكون المصفوتان on_true وon_false بالشكل نفسه. وهذا هو أيضًا شكل صفيف الإخراج. يجب أن تكون السمات في المصفوفة pred مماثلة لسمات on_true وon_false، مع نوع العنصر PRED.

بالنسبة إلى كل عنصر P من pred، يتم أخذ العنصر المقابل في صفيف الإخراج من on_true إذا كانت قيمة P هي true، ومن on_false إذا كانت قيمة P هي false. بما أنّه شكل محظور من البث، يمكن أن يكون pred عددًا متسلسلاً من النوع PRED. في هذه الحالة، يتم أخذ صفيف الإخراج بالكامل من on_true إذا كانت pred هي true، ومن on_false إذا كانت pred هي false.

مثال على pred غير متّجه:

let pred: PRED[4] = {true, false, false, true};
let v1: s32[4] = {1, 2, 3, 4};
let v2: s32[4] = {100, 200, 300, 400};
==>
Select(pred, v1, v2) = s32[4]{1, 200, 300, 4};

مثال على دالة قياسية pred:

let pred: PRED = true;
let v1: s32[4] = {1, 2, 3, 4};
let v2: s32[4] = {100, 200, 300, 400};
==>
Select(pred, v1, v2) = s32[4]{1, 2, 3, 4};

تتوفّر خيارات بين القوائم. تُعتبر القوائم المتعدّدة أنواعًا scalar لهذا الغرض. إذا كان on_true وon_false مجموعتَين من القيم (يجب أن يكون لهما الشكل نفسه)، يجب أن يكون pred عددًا متسلسلًا من النوع PRED.

SelectAndScatter

يمكنك الاطّلاع أيضًا على XlaBuilder::SelectAndScatter.

يمكن اعتبار هذه العملية عملية مركبة تحسب أولاً ReduceWindow على صفيف operand لاختيار عنصر من كل نافذة، ثم تبعثِر صفيف source على فهارس العناصر المحدّدة لمحاولة إنشاء صفيف ناتج بالشكل نفسه لصفيف الم Operand. تُستخدَم الدالة الثنائية select لاختيار عنصر من كل نافذة من خلال تطبيقها على كل نافذة، ويتمّ استدعاؤها مع السمة التي تجعل متجه فهرس المَعلمة الأولى أقلّ ترتيبًا أبجديًا من متجه فهرس المَعلمة الثانية. تعرِض الدالة select القيمة true إذا تم اختيار المَعلمة الأولى، وتعرِض القيمة false إذا تم اختيار المَعلمة الثانية، ويجب أن تحافظ الدالة على التسلسل (أي إذا كان select(a, b) وselect(b, c)true، يكون select(a, c) هو true أيضًا) لكي لا يعتمد العنصر المحدّد على ترتيب العناصر التي يتم التنقّل فيها خلال فترة زمنية معيّنة.

يتم تطبيق الدالة scatter على كل فهرس محدّد في صفيف الإخراج. ويقبل دالة الوسيط المتغير سمتَين قياسيتين:

  1. القيمة الحالية في الفهرس المحدّد في صفيف النتائج
  2. قيمة النقاط المتبعثرة من source التي تنطبق على الفهرس المحدّد

يجمع هذا الدالة بين المَعلمتَين ويعرض قيمة عددية تستخدم لتعديل القيمة في الفهرس المحدّد في صفيف الإخراج. في البداية، يتم ضبط جميع فهارس صفيف الإخراج على init_value.

يكون شكل مصفوفة الإخراج هو نفسه شكل مصفوفة operand، ويجب أن يكون شكل مصفوفة source هو نفسه شكل نتيجة تطبيق عملية ReduceWindow على مصفوفة operand. يمكن استخدام SelectAndScatter ل الانتشار العكسي لقيم التدرّج لطبقة تجميع في شبكة عصبية.

SelectAndScatter(operand, select, window_dimensions, window_strides, padding, source, init_value, scatter)

الوسيطات النوع الدلالات
operand XlaOp صفيف من النوع T تنزلق النوافذ فوقه
select XlaComputation عملية حسابية ثنائية من النوع T, T -> PRED، لتطبيقها على جميع العناصر في كل نافذة، تعرِض true في حال اختيار المَعلمة الأولى وتعرِض false في حال اختيار المَعلمة الثانية
window_dimensions ArraySlice<int64> صفيف من الأعداد الصحيحة لقيم سمة الفترة
window_strides ArraySlice<int64> صفيف من الأعداد الصحيحة لقيم خطوة النافذة
padding Padding نوع الحشو للنافذة (Padding::kSame أو Padding::kValid)
source XlaOp مصفوفة من النوع T تحتوي على القيم المطلوب بعثرها
init_value XlaOp قيمة عددية من النوع T للقيمة الأولية لصفيف الإخراج
scatter XlaComputation حساب ثنائي من النوع T, T -> T لتطبيق كل عنصر مصدر خطوط متقطعة مع عنصر الوجهة

يعرض الشكل أدناه أمثلة على استخدام SelectAndScatter، مع احتساب الدالة select للقيمة القصوى بين مَعلماتها. يُرجى العِلم أنّه عندما تتراكب النوافذ، كما هو موضّح في الشكل (2) أدناه، قد يتم اختيار فهرس مصفوفة operand عدة مرات من خلال نوافذ مختلفة. في الشكل، يتم اختيار العنصر الذي يمثّل القيمة 9 من خلال كلتا النافذتَين العلويتَين (الأزرق والأحمر)، وتُنشئ دالة الإضافة الثنائية scatter عنصر الإخراج الذي يمثّل القيمة 8 (2 + 6).

ترتيب تقييم الدالة scatter عشوائي وقد يكون غير محدّد. لذلك، يجب ألا تكون دالة scatter حساسة بشكل مفرط لإعادة الربط. اطّلِع على المناقشة حول الارتباط في سياق Reduce للحصول على مزيد من التفاصيل.

إرسال

يمكنك الاطّلاع أيضًا على XlaBuilder::Send.

Send(operand, channel_handle)

الوسيطات النوع الدلالات
operand XlaOp البيانات المطلوب إرسالها (صفيف من النوع T)
channel_handle ChannelHandle معرّف فريد لكل زوج من الإرسال/الاستلام

تُرسِل بيانات الم Operand المحدَّدة إلى Recv في عملية حسابية أخرى تشترك في معرّف القناة نفسه. لا تعرض أي بيانات.

على غرار عملية Recv، تمثّل واجهة برمجة التطبيقات للعميل لعملية Send التواصل غير المتزامن، ويتم تقسيمها داخليًا إلى تعليمات HLO بدورتين (Send وSendDone) لتفعيل عمليات نقل البيانات غير المتزامنة. يمكنك أيضًا الاطّلاع على HloInstruction::CreateSend وHloInstruction::CreateSendDone.

Send(HloInstruction operand, int64 channel_id)

تبدأ عملية نقل غير متزامنة للمَعلمة إلى الموارد التي تم تخصيصها باستخدام Recv مع معرّف القناة نفسه. تُعرِض سياقًا يتم استخدامه في SendDone التالي للانتظار إلى أن تكتمل عملية نقل البيانات. السياق هو مجموعة من {operand (shape), request identifier (U32)} ولا يمكن استخدامه إلا من خلال تعليمات SendDone.

SendDone(HloInstruction context)

استنادًا إلى سياق تم إنشاؤه بواسطة تعليمات Send، ينتظر اكتمال نقل البيانات. لا تعرض التعليمات أي بيانات.

تحديد موعد إرسال تعليمات القناة

في ما يلي ترتيب تنفيذ التعليمات الأربعة لكل قناة (Recv وRecvDone Send وSendDone).

  • يحدث Recv قبل Send
  • يحدث Send قبل RecvDone
  • يحدث Recv قبل RecvDone
  • يحدث Send قبل SendDone

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

يُرجى العلم أنّ القيود المفروضة على التعليمات لا تنطبق إلا على وحدات TPU أثناء التشغيل. على GPU، سيحظر send وrecv أي بيانات فعلية ولن يرسلاها إلا بعد إتمام عملية مصافحة بين الجهازَين المصدر والوجهة.

شريحة

يمكنك الاطّلاع أيضًا على XlaBuilder::Slice.

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

Slice(operand, start_indices, limit_indices, strides)

الوسيطات النوع الدلالات
operand XlaOp صفيف من N سمة من النوع T
start_indices ArraySlice<int64> قائمة بـ N عدد صحيح يحتوي على الفواصل الزمنية لبداية الشريحة لكل سمة يجب أن تكون القيم أكبر من أو تساوي صفرًا.
limit_indices ArraySlice<int64> قائمة بـ N عدد صحيح يحتوي على الفواصل النهائية (الحصرية) للقسم لكل سمة يجب أن تكون كل قيمة أكبر من أو تساوي قيمة start_indices الخاصة بالسمة وأقل من أو تساوي حجم السمة.
strides ArraySlice<int64> قائمة بـ N عدد صحيح يحدّد خطوة الإدخال للقسم تختار الشريحة كل strides[d] عنصر في السمة d.

مثال أحادي الأبعاد:

let a = {0.0, 1.0, 2.0, 3.0, 4.0}
Slice(a, {2}, {4}) produces:
  {2.0, 3.0}

مثال على القياس ثنائي الأبعاد:

let b =
 { {0.0,  1.0,  2.0},
   {3.0,  4.0,  5.0},
   {6.0,  7.0,  8.0},
   {9.0, 10.0, 11.0} }

Slice(b, {2, 1}, {4, 3}) produces:
  { { 7.0,  8.0},
    {10.0, 11.0} }

ترتيب

يمكنك الاطّلاع أيضًا على XlaBuilder::Sort.

Sort(operands, comparator, dimension, is_stable)

الوسيطات النوع الدلالات
operands ArraySlice<XlaOp> عناصر التشغيل المطلوب ترتيبها
comparator XlaComputation عملية حسابية المقارن لاستخدامها
dimension int64 السمة التي يتم الترتيب حسبها.
is_stable bool ما إذا كان يجب استخدام الترتيب الثابت

في حال تقديم عامل واحد فقط:

  • إذا كان الم Operand هو مصفوفة لاتّجاه واحد (صفيف)، تكون النتيجة صفيفًا مرتبًا. إذا كنت تريد ترتيب الصفيف بترتيب تصاعدي، يجب أن يُجري المقارن مقارنةً أقل من. بشكل رسمي، بعد ترتيب الصفيف، ينطبق ذلك على جميع مواضع الفهرس i, j مع i < j التي إما comparator(value[i], value[j]) = comparator(value[j], value[i]) = false أو comparator(value[i], value[j]) = true.

  • إذا كان المعامل يتضمّن عددًا أكبر من السمات، يتم ترتيب المعامل على طول السمة المقدَّمة. على سبيل المثال، بالنسبة إلى مصفوفة ثنائية الأبعاد (مكثّف)، ستحدّد قيمة السمة 0 ترتيب كل عمود بشكل مستقل، وستحدّد قيمة السمة 1 ترتيب كل صف بشكل مستقل. إذا لم يتم تحديد رقم سمة، يتم اختيار السمة الأخيرة تلقائيًا. بالنسبة إلى السمة التي يتمّ ترتيبها، ينطبق ترتيب الترتيب نفسه كما هو الحال في الحالة ذات السمة الواحدة.

في حال تقديم n > 1 عامل حسابي:

  • يجب أن تكون جميع عناصر n هي مصفوفات ذات الأبعاد نفسها. قد تختلف أنواع العناصر في مصفوفات السلاسل المتسلسلة.

  • يتم ترتيب جميع المعاملات معًا، وليس بشكل فردي. من الناحية المفهومية، تتم معاملة المَعلمات كمجموعة. عند التحقّق مما إذا كان يجب تبديل عناصر كلّ معامل في موضعَي الفهرس i وj، يتمّ استدعاء المقارن باستخدام 2 * n مَعلمة قياسية، حيث تتطابق المَعلمة 2 * k مع القيمة في الموضع i من المعامل k-th، وتتطابق المَعلمة 2 * k + 1 مع القيمة في الموضع j من المعامل k-th. وعادةً ما يقارن المقارن2 * k بين المَعلمتَين 2 * k و2 * k + 1 ويقارن ربما بين أزواج مَعلمات أخرى لتحديد الفائز في حال تساوي النتيجة.

  • والنتيجة هي مجموعة تتألف من المُعامِلات بترتيب مرتّب (بالاستناد إلى السمة المقدَّمة، كما هو موضّح أعلاه). يتوافق المعامل i-th للمجموعة مع المعامل i-th لدالة Sort.

على سبيل المثال، إذا كانت هناك ثلاثة عناصر تشغيل هي operand0 = [3, 1] وoperand1 = [42, 50] وoperand2 = [-3.0, 1.1]، وكان المقارن يقارن قيم operand0 فقط باستخدام عامل التشغيل "أقل من"، تكون نتيجة الترتيب هي السلسلة الهرمية ([1, 3], [50, 42], [1.1, -3.0]).

في حال ضبط is_stable على true، يُضمن أنّ الترتيب ثابت، أي إذا كانت هناك عناصر يُعتبرها المقارن متساوية، يتم الاحتفاظ بالترتيب النسبي للقيم المتساوية. يكون العنصران e1 وe2 متساويين إذا كان comparator(e1, e2) = comparator(e2, e1) = false فقط. يتم تلقائيًا ضبط is_stable على false.

TopK

يمكنك الاطّلاع أيضًا على XlaBuilder::TopK.

تبحث دالة TopK عن قيم ومؤشرات k أكبر أو أصغر العناصر للبعد الأخير من مصفوفة السلاسل المتعدّدة المحدّدة.

TopK(operand, k, largest)

الوسيطات النوع الدلالات
operand XlaOp مصفوفة السلاسل المتسلسلة التي يتم استخراج أهم k عنصر منها يجب أن يكون للمصفّح قياس واحد أو أكثر. يجب أن يكون حجم السمة الأخيرة من مصفوفة السلاسل المتسلسلة أكبر من أو يساوي k.
k int64 عدد العناصر المطلوب استخراجها.
largest bool لتحديد ما إذا كنت تريد استخراج أكبر أو أصغر k عنصر.

بالنسبة إلى مصفوفة إدخال أحادية البعد (صفيف)، يبحث عن k أكبر أو أصغر إدخالَين في الصفيف ويعرض مجموعة من صفيفَين (values, indices). وبالتالي، values[j] هو أكبر/أصغر إدخال في operand في j، فهرسه هو indices[j].

بالنسبة إلى مصفوفة تنشيط الإدخال التي تحتوي على أكثر من سمة واحدة، يتم احتساب أهم k إدخال على طول السمة الأخيرة، مع الحفاظ على جميع السمات الأخرى (الصفوف) في الإخراج. وبالتالي، بالنسبة إلى عامل تشغيل على شكل [A, B, ..., P, Q] حيث Q >= k، تكون النتيجة مجموعة (values, indices) حيث:

values.shape = indices.shape = [A, B, ..., P, k]

إذا كان عنصران في صف متساويان، يظهر العنصر الذي يملك الفهرس الأدنى أولاً.

تبديل

راجِع أيضًا عملية tf.reshape.

Transpose(operand)

الوسيطات النوع الدلالات
operand XlaOp الم Operand الذي سيتم تبديله
permutation ArraySlice<int64> كيفية تبديل السمات

تبدِّل سمات الم Operand باستخدام الترتيب المحدَّد، أي ∀ i . 0 ≤ i < number of dimensions ⇒ input_dimensions[permutation[i]] = output_dimensions[i].

وهذا هو نفسه Reshape(operand, permutation, Permute(permutation, operand.shape.dimensions)).

TriangularSolve

يمكنك الاطّلاع أيضًا على XlaBuilder::TriangularSolve.

لحل أنظمة المعادلات الخطية ذات المصفوفات المثلثية السفلية أو العليا عن طريق التعويض الأمامي أو العكسي. من خلال البث على طول سمات الأولوية، تحلّ سلسلة الإجراءات هذه أحد أنظمة المصفوفات op(a) * x = b أو x * op(a) = b للمتغيّر x، مع الأخذ في الاعتبار a وb، حيث يكون op(a) إما op(a) = a أو op(a) = Transpose(a) أو op(a) = Conj(Transpose(a)).

TriangularSolve(a, b, left_side, lower, unit_diagonal, transpose_a)

الوسيطات النوع الدلالات
a XlaOp صفيف أبعاده أكبر من اثنين من النوع المركّب أو النوع العشري الفارسي بالتنسيق [..., M, M]
b XlaOp صفيف أبعاده أكبر من 2 من النوع نفسه بالتنسيق [..., M, K] إذا كانت left_side صحيحة، [..., K, M] في الحالات الأخرى
left_side bool تشير إلى ما إذا كان يجب حلّ نظام من النوع op(a) * x = b (true) أو x * op(a) = b (false).
lower bool ما إذا كنت تريد استخدام المثلث العلوي أو السفلي من a
unit_diagonal bool إذا كانت true، يُفترض أنّ العناصر القطرية في a هي 1 ولا يتم الوصول إليها.
transpose_a Transpose ما إذا كان يجب استخدام a كما هي أو نقلها أو أخذ نقلها المزدوج

لا تتم قراءة بيانات الإدخال إلا من المثلث السفلي/العلوي من a، استنادًا إلى قيمة lower. ويتم تجاهل القيم من المثلث الآخر. يتم عرض بيانات الإخراج في المثلث نفسه، أما القيم في المثلث الآخر فتكون محددة من خلال التنفيذ ويمكن أن تكون أيّ شيء.

إذا كان عدد سمات a وb أكبر من 2، يتم التعامل معهما كحِزم من المصفوفات، حيث تكون جميع السمات سوى السمتَين الثانويتَين هي سمات الحِزم. يجب أن يكون لـ a وb سمات حِزم متساوية.

Tuple

يمكنك الاطّلاع أيضًا على XlaBuilder::Tuple.

مجموعة تحتوي على عدد متغيّر من عناصر بيانات، ولكل منها شكل خاص به

وهذا مشابه لـ std::tuple في C++. من الناحية النظرية:

let v: f32[10] = f32[10]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
let s: s32 = 5;
let t: (f32[10], s32) = tuple(v, s);

يمكن تحليل المجموعات (الوصول إليها) من خلال عملية GetTupleElement.

في حين

يمكنك الاطّلاع أيضًا على XlaBuilder::While.

While(condition, body, init)

الوسيطات النوع الدلالات
condition XlaComputation دالة XlaComputation من النوع T -> PRED التي تحدِّد شرط إنهاء الحلقة
body XlaComputation دالة XlaComputation من النوع T -> T التي تحدِّد نص الحلقة
init T القيمة الأولية للمَعلمتَين condition وbody

تنفيذ body بشكل تسلسلي إلى أن يتعذّر تنفيذ condition يشبه هذا الإجراء حلقة while النموذجية في العديد من اللغات الأخرى باستثناء الاختلافات والحدود المفروضة أدناه.

  • تعرض عقدة While قيمة من النوع T، وهي النتيجة من التنفيذ الأخير لـ body.
  • يتم تحديد شكل النوع T بشكل ثابت ويجب أن يكون متطابقًا في جميع النُسخ.

يتمّ إعداد مَعلمات T للعمليات الحسابية باستخدام قيمة init في الخطوة الأولى، ويتمّ تعديلها تلقائيًا إلى النتيجة الجديدة من body في كلّ خطوة لاحقة.

من حالات الاستخدام الرئيسية لعقدة While هي تنفيذ التنفيذ المتكرّر ل التدريب في الشبكات العصبية. يظهر أدناه رمز برمجي وهمي مبسّط مع رسم بياني يمثّل العملية الحسابية. يمكن العثور على الرمز في while_test.cc. النوع T في هذا المثال هو Tuple يتألّف من int32 لعدد المرات وvector[10] للمركم. على مدار 1000 تكرار، تستمر السلسلة المغلقة في إضافة متجه ثابت إلى المُجمِّع.

// Pseudocode for the computation.
init = {0, zero_vector[10]} // Tuple of int32 and float[10].
result = init;
while (result(0) < 1000) {
  iteration = result(0) + 1;
  new_vector = result(1) + constant_vector[10];
  result = {iteration, new_vector};
}