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

يوضِّح ما يلي دلالات العمليات المحدّدة في واجهة 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 صفًا من المصفوفات، يتم تنفيذ الاختزال الكلي على كل عنصر في الصف.
  • تمثّل 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: تحتوي كل ReplicaGroup على قائمة بأرقام تعريف النسخ المتماثلة المشاركة في العملية الحسابية (يمكن استرداد معرف النسخة المتماثلة للنسخة المماثلة الحالية باستخدام 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 فارغة، تنتمي جميع النُسخ المطابقة إلى مجموعة واحدة، وذلك بترتيب التسلسل الذي تظهر به.

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

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

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

الوسيطات النوع دلالات الألفاظ
operand XlaOp مصفوفة إدخال من n سمة
split_dimension int64 قيمة في الفاصل [0, n) تحدد البعد الذي يتم تقسيم المعامل عليه
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 أجزاء بطول البعد 0، بحيث يكون لكل جزء شكل f32[4,4]. يتم توزيع الأجزاء الأربعة على جميع النوى. بعد ذلك، يُنشئ كل مركز تسلسل للأجزاء المستلمة باستخدام البعد 1، بترتيب النواة 0-4. وبالتالي، يكون شكل الإخراج على كل نواة هو f32[16,4].

BatchNormGrad

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

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

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

الوسيطات النوع الدلالات
operand XlaOp صفيف الأبعاد عدد n المطلوب تسويتها (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 عبر سلسلة Bitcast، وسيتحوّل عنصر 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> السمة في الشكل المستهدَف التي تتطابق مع كل سمة من سمات شكل المُعامِل

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

يتم بث operand إلى الشكل الموضّح في out_dim_size. يعيّن broadcast_dimensions أبعاد 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.

Cholesky

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

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

Cholesky(a, lower)

الوسيطات النوع الدلالات
a XlaOp مصفوفة ترتيب > 2 من نوع معقد أو نقطة عائمة
lower bool ما إذا كنت تريد استخدام المثلث العلوي أو السفلي من a

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

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

إذا كان ترتيب a أكبر من 2، يتم التعامل مع 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

يحلّ التصغير محل المجموعة الفرعية المحدّدة من أبعاد المعامل باستخدام بُعد واحد. وسيطات الإدخال هي مصفوفة عشوائية من النوع 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 حوسبة النوع \(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 حاسوبات Xla من النوع \(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> مصفوفة n-d من خطوات النواة
padding ArraySlice< pair<int64,int64>> مصفوفة n-d من المساحة المتروكة (منخفضة، عالية)
lhs_dilation ArraySlice<int64> صفيف عامل تمدد lhs ذي الأبعاد n
rhs_dilation ArraySlice<int64> مصفوفة عامل التوسع n-d rhs
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)، ستكون هناك مساحة متروكة بمقدار صفرَين على اليسار و3 أصفار على اليمين في البُعد المكاني الثاني. يتساوى استخدام المساحة المتروكة مع إدخال تلك القيم الصفرية نفسها في الإدخال (lhs) قبل إجراء الالتفاف.

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

يُعرف تمدد الجانب الأيمن من المعادلة أيضًا باسم "التفافة المُعدَّلة". لمزيد من التفاصيل، يُرجى الاطّلاع على tf.nn.atrous_conv2d. ويُعرف تمدد lhs أيضًا باسم التفاف المُعاد ترتيبه. لمزيد من التفاصيل، يُرجى الاطّلاع على 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. وبشكل فعّال، نقسّم كل مجموعة من الرموز إلى مجموعات batch_group_count، ونفعل الشيء نفسه مع ميزات الناتج. بعد ذلك، لكل مجموعة من هذه المجموعات، نجري عمليات التفاف زوجي وننشئ تسلسلاً للناتج على طول بُعد ميزة الإخراج. تظل الدلالة التشغيلية لجميع الأبعاد الأخرى (الميزة والمكان) كما هي.

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

لوصف ما تفعله عملية الالتفاف، نأخذ عملية لفّ ثنائية الأبعاد ونختار بعض إحداثيات batch وz و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 تسلسل ن 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

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

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

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

DotGeneral

راجِع أيضًا XlaBuilder::DotGeneral.

DotGeneral(lhs, rhs, dimension_numbers)

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

هذه الطريقة مشابهة للنقطة، ولكنّها تسمح بتحديد أرقام السمات المتعاقدة والأبعاد المجمّعة لكل من 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 هو ترتيب == 1، مع حجم السمة يساوي ترتيب 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 هو ترتيب == 1، مع حجم السمة يساوي ترتيب 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 هو نفسه كما هو موضّح أعلاه. يجب استخدام هذا المتغير من العملية في العمليات الحسابية بين الصفائف ذات الترتيبات المختلفة (مثل إضافة مصفوفة إلى متجه).

عامل التشغيل 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 هو نفسه كما هو موضّح أعلاه. يجب استخدام هذا المتغير من العملية لإجراء عمليات المقارنة بين الصفائف ذات الصفوف المختلفة (مثل إضافة مصفوفة إلى متجه).

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

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

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

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

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

Ceil(operand) العنصر المرئي في صورة 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). إذا كان المعامل نوع نقطة عائمة، سيتم عرض القيمة 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) النفي المنطقي للعنصر 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 "FFT" معكوس من المعقد إلى المعقد الشكل لم يتغيّر.
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، ولهذا السبب، فإنّ محور التحويل الداخلي هو الذي يغيّر الحجم. ستكون عمليات تحويل المحاور الأخرى بعد ذلك معقدة->معقدة.

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

إنّ وحدة المعالجة المركزية CPU (سرعة الاستجابة السريعة) مدعومة بمعيار TensorFFT من Eigen. تستخدم تحويلة فورييه باستخدام وحدة معالجة الرسومات cuFFT.

جمع

تعمل عملية التجميع في 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> مجموعة السمات في شكل الإخراج التي يتمّ إزاحتها إلى صفيف تمّ تقطيعه من المُشغّل
slice_sizes ArraySlice<int64> slice_sizes[i] هي حدود الشريحة في البُعد i.
collapsed_slice_dims ArraySlice<int64> مجموعة السمات في كل شريحة تم تصغيرها يجب أن يكون لهذه الأبعاد المقاس 1.
start_index_map ArraySlice<int64> خريطة توضّح كيفية ربط الفهارس في start_indices بالفهارس القانونية في معامل.
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]، وبالتالي يمكن تمثيل المجموعة المؤلفة من 5 مواضع على شكل مصفوفة 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. يمكننا ضبط السمات في شكل الإخراج التي تمثّل سمات الإزاحة (السمات التي تحتوي على O0 وO1 في المثال الأخير). يتمّ تعريف سمات حِزم الإخراج (السمات التي تحتوي على G0 وG1 في المثال الأخير) على أنّها سمات الإخراج التي ليست سمات تمكين.

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

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

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

يتم استخدام G0 وG1 لقطع فهرس بدء من صفيف فهارس التجميع كالمعتاد، باستثناء أنّ الفهرس البدءي يحتوي على عنصر واحد فقط، وهو X. وبالمثل، هناك فهرس واحد فقط لموضع الإزاحة في الإخراج بالقيمة O0. start_index_mapremapped_offset_dimsXX000000000OOOOGGGG11GatherIndicestf.gather_nd

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

GetDimensionSize

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

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

GetDimensionSize(operand, dimension)

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

SetDimensionSize

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

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

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 تسلسل ن 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 مع channel_id نفسه عرض سياق للموارد المخصصة الذي يستخدمه تعليمات RecvDone التالية لانتظار اكتمال عملية نقل البيانات. والسياق عبارة عن صف من {pay 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.

تقلِّل هذه العملية سمة واحدة أو أكثر من كل صفيف إدخال إلى مقاييس قياسية. ترتيب كل صفيف معروض هو rank(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 rank 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]

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

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

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

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

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

|  4   8  12 |
| 16  20  24 |

إذا قللنا البعد 2، نحصل أيضًا على مصفوفة الترتيب 2 حيث تم طي جميع القيم عبر البُعد 2 في مقياس رقمي:

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

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

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

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

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

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

  • تنفيذ قيمة مخفَّضة للمعامل الأول
  • ...
  • تنفيذ قيمة مخفضة للمعامل N
  • قيمة الإدخال للمعامل الأول
  • ...
  • إدخال قيمة للمعامل 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.

خفض Scatter هو عملية جماعية تُنفِّذ AllOrder بشكل فعّال، ثم توزع النتيجة بتقسيمها إلى كتل 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]. يعمل تشغيل النافذة المصغّرة فوق المصفوفة المقسّمة على ثلاث نوافذ [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, new_sizes) Reshape(operand, dimensions, new_sizes)

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

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

على سبيل المثال، لنفترض أنّ 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} } };

In-order collapse:
let v012_24 = Reshape(v, {0,1,2}, {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, {0,1,2}, {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} };

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

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


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

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

Reshape(f32[1x1] { {5} }, {0,1}, {}) == 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.

تُنشئ دالة RAND_MAX ناتجًا بشكل معيّن باستخدام أرقام عشوائية يتم إنشاؤها باتّباع \(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[دمج(G, i)] حيث يؤدي الجمع(أ، ب) إلى إدراج 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 معرّف فريد لكل زوج من عمليات الإرسال/الإرسال

تُرسِل بيانات المُشغِّل المحدَّدة إلى تعليمات 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

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

شريحة

راجِع أيضًا 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 إلى ترتيب كل صف بشكل مستقل. في حال عدم تقديم رقم سمة، يتم اختيار السمة الأخيرة تلقائيًا. بالنسبة إلى السمة التي يتم ترتيبها، ينطبق ترتيب الترتيب نفسه كما هو الحال في حالة الترتيب 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.

تبديل

اطّلِع أيضًا على عملية tf.reshape.

Transpose(operand)

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

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

وهذا هو نفسه Reshape(المعامل, التباديل, 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 صفيف من الرتبة > 2 من النوع المركّب أو النوع الفاصل العائم بالتنسيق [..., 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};
}