دلالة العملية

فيما يلي وصف دلالات العمليات المحددة في واجهة XlaBuilder. في العادة، تربط هذه العمليات واحدًا لواحد بالعمليات المحددة في واجهة RPC في xla_data.proto.

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

AfterAll

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

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

AllToAll

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

AllToAll هي عملية جماعية ترسل البيانات من كل النوى إلى جميع النوى. وهي تشمل مرحلتين:

  1. مرحلة التبعثر. في كل نواة، ينقسم المعامل إلى split_count عدد من الكتل على طول split_dimensions، وتنتشر الكتل إلى كل النوى، على سبيل المثال يتم إرسال الكتلة الأولى إلى النواة الأولى.
  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.
  • شكل المعامل ليس صفًا.

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.

يتم تعريف التدرجات الثلاثة باستخدام الصيغ التالية (على افتراض مصفوفة رباعية الأبعاد مثل 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 ($\nabl x$)
grad_scale XlaOp التدرج بالنسبة إلى الإدخال scale ($\nabl \gamma$)
grad_offset XlaOp التدرج بالنسبة إلى الإدخال offset($\nabl \beta$)

BatchNormInference

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

تطبيع صفيف عبر الأبعاد المجمعة والأبعاد المكانية.

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

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

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

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

والمُخرج هو صفيف ذو أبعاد نيّة له شكل الإدخال operand نفسه.

BatchNormTraining

راجِع أيضًا XlaBuilder::BatchNormTraining وthe original batch normalization paper للحصول على وصف تفصيلي للخوارزمية.

تطبيع صفيف عبر الأبعاد المجمعة والأبعاد المكانية.

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

الوسيطات النوع دلالات الألفاظ
operand XlaOp صفيفة الأبعاد n المطلوب تسويتها (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 عبارة عن مصفوفة رباعية الأبعاد):

  • تحسب متوسط الدفعة \(\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\)

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

نوع الإخراج هو صف من ثلاث ثوانٍ من 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

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

يجب ألا يكون نوعا عنصر المصدر والوجهة صفوفًا.

تحويل البث الرقمي إلى نوع أساسي بعرض مختلف

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}.

فهرس السمات الجديد إلى نُسخ من المعامل، أي

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

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

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

الاتصال

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

استدعاء عملية حسابية مع الوسيطات المقدمة.

Call(computation, args...)

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

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

تشوليسكي

يمكنك أيضًا الاطّلاع على 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:

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

تسلسل

يمكنك أيضًا الاطّلاع على 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 معالجة Xlaللنوع \(T_0 \to S\)
false_operand XlaOp الوسيطة من النوع \(T_1\)
false_computation XlaComputation معالجة Xlaللنوع \(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.

الإحالات الناجحة (الالتفاف)

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

كـ ConsWithGeneralPadding، ولكن يتم تحديد المساحة المتروكة بطريقة مختصرة على أنها SAME أو ACTIVE. تؤدي المساحة المتروكة نفسها إلى توفير مساحة الإدخال (lhs) بالأصفار حتى يكون للمخرجات نفس شكل الإدخال عند عدم الانتقال إلى الحساب. المساحة المتروكة "صالحة" تعني ببساطة عدم وجود مساحة متروكة.

conversionWithGeneralPadding (الالتفاف)

يمكنك أيضًا الاطّلاع على 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> مصفوفة عامل التوسعة n-d lh
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: لكل موضع (ص,س) في مساحة القاعدة خط متجه مرتبط به، ويدخل في هذا البُعد.
  • spatial_dims: يصف الأبعاد المكانية n التي تحدد مساحة القاعدة التي تتحرك عبرها النافذة.

الوسيطة rhs هي مصفوفة ترتيب n+2 تصف الفلتر/النواة/النافذة الالتفافية. تكون الأبعاد بهذا الترتيب:

  • output-z: السمة z للناتج.
  • input-z: يجب أن يساوي حجم هذا البُعد مضروبًا في feature_group_count حجم البُعد z بالأرقام lh.
  • 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 عامل الاتساع الذي سيتم تطبيقه على قيم hs وrhs على التوالي، في كل بُعد مكاني. إذا كان عامل الاتساع في بُعد مكاني هو d، فسيتم وضع ثقوب d-1 ضمنيًا بين كل إدخال من الإدخالات في هذا البعد، مما يزيد من حجم المصفوفة. الثقوب مليئة بقيمة بيئة مستقلة، والتي تعني الالتفاف صفر.

يسمى اتساع Rhs أيضًا التواء الحاد. ولمزيد من التفاصيل، يمكنك الاطّلاع على tf.nn.atrous_conv2d. يُطلق على اتساع نظام خط تشبيك (Hs) أيضًا اسم الالتفاف المنقول. لمزيد من التفاصيل، يُرجى الاطّلاع على 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-th معًا لحساب 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 بالأرقام lh.
  • z: الحجم نفسه مثل output-z على النواة (rhs).
  • spatial_dims: قيمة واحدة لكل موضع صالح للنافذة الالتفافية.

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

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

لوصف ما يفعله الالتفاف، ضع في الاعتبار الالتفاف الثنائي الأبعاد واختر بعض إحداثيات batch وz وy وx الثابتة في الإخراج. وعندئذٍ، تمثّل (y,x) موضعًا من زاوية النافذة ضمن مساحة القاعدة (مثل الزاوية العلوية اليسرى، حسب طريقة تفسيرك للأبعاد المكانية). لدينا الآن نافذة ثنائية الأبعاد، مأخوذة من مساحة القاعدة، حيث ترتبط كل نقطة ثنائية الأبعاد بمتجه أحادي الأبعاد، ولذلك نحصل على مربع ثلاثي الأبعاد. من النواة الالتفافية، بما أننا أصلحنا إحداثي الإخراج 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

يجب أن تتطابق أبعاد المعامل والشكل المستهدف. يجب ألا يكون نوعا عنصر المصدر والوجهة صفوفًا.

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

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

CrossReplicaSum

لإجراء AllReduce مع حساب مجموع.

CustomCall

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

استدعِ دالة مقدَّمة من المستخدِم ضمن عملية حاسوبية.

CustomCall(target_name, args..., shape)

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

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

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

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

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

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

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

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

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

نقطة

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

Dot(lhs, rhs)

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

وتعتمد دلالات هذه العملية على تصنيفات المعاملات:

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

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

DotGeneral

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

DotGeneral(lhs, rhs, dimension_numbers)

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

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

حقول DotdimensionNumbers النوع دلالات الألفاظ
lhs_contracting_dimensions int64 متكرّر رقما بُعد متعاقدين (lhs)
rhs_contracting_dimensions int64 متكرّر رقما بُعد متعاقدين (rhs)
lhs_batch_dimensions int64 متكرّر lhs أرقام أبعاد مجمّعة
rhs_batch_dimensions int64 متكرّر rhs أرقام أبعاد مجمّعة

تنفِّذ DotGeneral مجموع المنتجات على أبعاد التعاقد المحدّدة في dimension_numbers.

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

مثال مع أرقام أبعاد التعاقد:

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

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

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

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

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

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

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

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

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

DotGeneral(lhs, rhs, dnums) -> { { {1.0, 2.0},
{3.0, 4.0} },
{ {5.0, 6.0},
{7.0, 8.0} } }
إدخال الناتج دلالات الألفاظ
[b0, m, k] dot [b0, k, n] [b0, m, n] مادة عرض مجمّعة
[b0, b1, m, k] dot [b0, b1, k, n] [b0 ، b1 ، m ، n] مادة عرض مجمّعة

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

DynamicSlice

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

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

DynamicSlice(operand, start_indices, size_indices)

الوسيطات النوع دلالات الألفاظ
operand XlaOp صفيف الأبعاد N من النوع T
start_indices تسلسل N XlaOp قائمة بعدد صحيح عددي يحتوي على مؤشرات بدء الشريحة لكل بُعد. يجب أن تكون القيمة أكبر من صفر أو تساويه.
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 تحتوي على تعديل الشريحة. يجب أن يكون كل بُعد لشكل التحديث أكبر من الصفر تمامًا، ويجب أن تكون بداية + التحديث أقل من أو تساوي حجم المعامل لكل بُعد لتجنب إنشاء فهارس تحديث خارج الحدود.
start_indices تسلسل N XlaOp قائمة بعدد صحيح عددي يحتوي على مؤشرات بدء الشريحة لكل بُعد. يجب أن تكون القيمة أكبر من صفر أو تساويه.

يتم حساب فهارس الشرائح الفعالة من خلال تطبيق التحويل التالي لكل فهرس 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 (القسمة) أو Rem (المتبقي) أو Max (الحد الأقصى) أو Min (الحد الأدنى) أو LogicalAnd (المنطقي AND) أو LogicalOr (منطقية OR).

الوسيطات النوع دلالات الألفاظ
lhs XlaOp معامل الجانب الأيسر: صفيف من النوع T
rhs XlaOp معامل الجانب الأيمن: صفيف من النوع T

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

عندما تكون 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 N +Infinite <+0 N +Finite<.

الوسيطات النوع دلالات الألفاظ
lhs XlaOp معامل الجانب الأيسر: صفيف من النوع T
rhs XlaOp معامل الجانب الأيمن: صفيف من النوع T

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

هناك صيغة بديلة تتيح بثًا صوتيًا من ترتيب مختلف للعمليات التالية:

Op(lhs, rhs, broadcast_dimensions)

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

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

الدوال الأحادية من حيث العناصر

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

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

Ceil(operand) عنصر القائمة على العناصر x -> ⌈x⌉.

Cos(operand) جيب التمام x -> cos(x) في منظور العناصر

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

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

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

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

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

LogicalNot(operand) عنصر منطقي من حيث العناصر وليس x -> !(x).

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

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

Neg(operand) رمز نفي من حيث العناصر x -> -x.

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

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.

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

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

Tanh(operand) المماس الزائدي على مستوى العناصر x -> tanh(x).

Round(operand) التقريب إلى قيمة العناصر في كل عنصر، وهو يؤدي إلى الانتقال من الصفر.

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

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

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

Fft

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

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

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

ميزة "FFT" متعددة الأبعاد

عند توفير أكثر من fft_length واحد، يعادل ذلك تطبيق سلسلة من عمليات النقل في الوقت الفعلي (FFT) على كل من المحاور الداخلية. لاحظ أنه بالنسبة للحالات الحقيقية >المعقدة والمعقدة->يتم تحويل المحور الداخلي (بشكل فعال) أولاً (RFFT; الأخير لـ IRFFT)، وهذا هو السبب في أن المحور الداخلي هو الذي يتغير الحجم. ستكون حينئذٍ تحويلات المحاور الأخرى معقدة->معقدة.

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

تتوافق وحدة المعالجة المركزية FFT مع TensorFFT من Eigen. يستخدم GPU FFT 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 ما إذا كان بإمكان المتصل ترتيب الفهارس مضمونها أم لا.
unique_indices bool ما إذا كان المتصل يضمن أن تكون المؤشرات فريدة.

ولتسهيل الأمر، نصنّف السمات في مصفوفة الإخراج وليس في offset_dims على أنّها batch_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 ضمنيًا أنّ شكل 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 (أي أنّ القيمة adjusted_slice_sizes تساوي offset_dims[k] لبعض القيم k)، نختار الحد المناظِر من slice_sizes بعد احتساب collapsed_slice_dims (مثلاً، نختار adjusted_slice_sizes[k] حيث تكون adjusted_slice_sizes هي slice_sizes مع إزالة الحدود في الفهارس collapsed_slice_dims).

رسميًا، يتم حساب فهرس المعامل In المقابل لفهرس الناتج Out على النحو التالي:

  1. اسمح G = { Out[k] لـ k في batch_dims }. استخدِم G لتقسيم الاتجاه S بحيث S[i] = start_indices[دمج(G، i)] حيث تؤدي الدمج(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 على "صحيح"، يمكن لخوارزمية XLA أن تفترض أنّ start_indices تم ترتيبها (بترتيب start_index_map تصاعديًا) حسب المستخدم. إذا لم تكن كذلك، فسيتم تحديد دلالات التنفيذ.

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

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

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

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

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

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

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

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

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

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

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

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

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

تعمل عملية التجميع هذه كشريحة ديناميكية مجمَّعة مع G كسمة مجمّعة.

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

تعمل هذه الطريقة أيضًا كشريحة ديناميكية مجمّعة G0 و G1 كأبعاد مجمّعة. لا يزال حجم الشريحة [8,6].

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

  1. يمكننا تحديد الأبعاد في شكل الإخراج التي تمثل أبعاد الإزاحة (السمات التي تحتوي على 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_map في الوصف الرسمي) و "Offset Mapping" (remapped_offset_dims في الوصف الرسمي) إلى [X و0] و[0 وO0] على التوالي، مع إضافة ما يصل إلى [X,O0] إلى القيم00000OOGGGG11GatherIndicestf.gather_nd

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

GetDimensionSize

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

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

GetDimensionSize(operand, dimension)

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

SetDimensionSize

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

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

SetDimensionSize(operand, size, dimension)

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

المرور عبر المعامل نتيجةً لذلك، مع تتبع البُعد الديناميكي بواسطة برنامج التحويل.

وسيتم تجاهل القيم المحشوّة من خلال عمليات التقليل من انتقال البيانات.

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 من البيانات. يُسمح بإجراء عمليات متعددة للخلاصة في العملية الحسابية، ولكن يجب أن يكون هناك ترتيب إجمالي بين عمليات الخلاصة. على سبيل المثال، لاثنتين من خلاصات Infeed في التعليمات البرمجية أدناه ترتيب إجمالي نظرًا لوجود تبعية بين التكرارات الحلقية while.

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

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

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

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

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

Iota(shape, iota_dimension)

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

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

على سبيل المثال، يتم إرجاع قيمة Iota(s32[4, 8], 0).

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

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

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

خريطة

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

Map(operands..., computation)

الوسيطات النوع دلالات الألفاظ
operands تسلسل N XlaOps 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 مختلفة لمصفوفة ثنائية الأبعاد.

الإشعارات

يمكنك أيضًا الاطّلاع على 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 التالية لانتظار اكتمال عملية نقل البيانات. السياق هو صف من {Get buffer (shape), requestidentifier (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 باستخدام دالة "add":

لاحظ أن نتيجتي الاختزال عبارة عن صفائف أحادي البُعد. يظهر المخطط واحدًا كعمود والآخر كصف فقط للراحة البصرية.

لمثال أكثر تعقيدًا، إليك صفيف ثلاثي الأبعاد. وترتيبه هو 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 الصفيف أحادي البُعد [20, 28, 36].

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

فارياديك فري

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

  • جارٍ تنفيذ القيمة المخفَّضة للمعامل الأول
  • ...
  • جارٍ تشغيل القيمة المخفضة للمعامل N
  • قيمة الإدخال للمعامل الأول
  • ...
  • قيمة الإدخال للمعامل "ن"

على سبيل المثال، بالنظر إلى دالة الاختزال التالية، التي يمكن استخدامها لحساب الحد الأقصى وargmax لصفيف 1-D بالتوازي:

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. ويتم تقريب قيم الإدخال إلى أقرب قيمة يمكن تمثيلها بعدد معين من وحدات بت mantisa (باستخدام دلالات "الارتباطات الزوجية")، وأي قيم تتجاوز النطاق المحدد بعدد وحدات البت الأسية يتم تثبيتها على ما لا نهاية موجبة أو سالبة. يتم الاحتفاظ بقيم NaN على الرغم من إمكانية تحويلها إلى قيم NaN الأساسية.

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

ReduceScatter

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

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

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

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

ويكون شكل الناتج هو شكل الإدخال الذي تم فيه تصغير حجم scatter_dimension بمقدار shard_count مرة. على سبيل المثال، إذا كان هناك نسختان طبق الأصل وكان المعامل يتضمن القيمة [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 تسلسل من الصفائف متعددة الأبعاد N من الأنواع T_0,..., T_{N-1}، ويمثل كل منها مساحة القاعدة التي يتم وضع النافذة عليها.
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 نوع المساحة المتروكة للنافذة (المساحة المتروكة::kSame، والتي يتم وضعها بحيث يكون لها شكل الإخراج نفسه مثل المدخل إذا كانت الخطوة 1، أو المساحة المتروكة::kصالحة التي لا تستخدم مساحة متروكة و "توقف" النافذة عند عدم ملاءمتها)

المكان:

  • يجب أن تكون 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.

لعرض المعرف الفريد (مقياس U32) للنسخة المطابقة.

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 الخط المتجه لأحجام الأبعاد الجديدة

نظريًا، تقوم إعادة تشكيل الصفيف أولاً بتسطيح صفيف في متجه أحادي البعد لقيم البيانات، ثم تنقيح هذا المتجه في شكل جديد. وسيطات الإدخال هي صفيف عشوائي من النوع T، ومتجه ثابت في وقت التجميع لمؤشرات الأبعاد، ومتجه ثابت في وقت التجميع لأحجام الأبعاد للنتيجة. يجب أن تكون القيم في الخط المتجه dimension، إذا تم توفيرها، تبديلاً لجميع أبعاد حرف T، وتكون القيمة التلقائية عند عدم تقديمها هي {0, ..., rank - 1}. ترتيب الأبعاد في dimensions هو من البُعد الأبطأ تغيُّرًا (الأكثر أهمية) إلى البعد الأسرع متغيرًا (الأصغر) في تداخل الحلقة التي تعمل على تصغير صفيف الإدخال إلى بُعد واحد. يحدد الخط المتجه new_sizes حجم صفيف الإخراج. القيمة في الفهرس 0 بـ new_sizes هي حجم البُعد 0، والقيمة في الفهرس 1 هي حجم البُعد 1، وهكذا. يجب أن يكون ناتج الأبعاد new_size مساويًا لمنتج أحجام أبعاد المعامل. عند تحسين الصفيف المصغّر إلى مصفوفة متعددة الأبعاد المحدّدة في 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(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.

تنشئ ناتجًا لشكل معيّن بأرقام عشوائية يتم إنشاؤها بعد التوزيع الطبيعي. \(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

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

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

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

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

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

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

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

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

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

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

وللحصول على وصف تفصيلي وأمثلة غير رسمية، يمكنك مراجعة قسم "الوصف غير الرسمي" ضمن 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};

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

SelectAndScatter

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

يمكن اعتبار هذه العملية عملية مركّبة تحسب أولاً ReduceWindow في الصفيف operand لاختيار عنصر من كل نافذة، ثم تبعثر بعد ذلك صفيف source على فهارس العناصر المحدّدة لإنشاء صفيف ناتج بنفس شكل مصفوفة المعامل. تُستخدَم الدالة 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 نوع المساحة المتروكة للنافذة (المساحة المتروكة::kSame أو الحشو::kصالح)
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), الطلب (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 ما إذا كان يجب استخدام الترتيب الثابت.

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

  • إذا كان المعامل صفيفًا من الترتيب 1 (صفيف)، تكون النتيجة صفيفًا تم فرزه. إذا كنت تريد فرز الصفيفة بترتيب تصاعدي، فيجب على المقارِن إجراء مقارنة "أقل من". رسميًا، بعد فرز المصفوفة، فإنها تحتفظ بجميع مواضع الفهرس i, j التي تحتوي على i < j والتي تكون comparator(value[i], value[j]) = comparator(value[j], value[i]) = false أو comparator(value[i], value[j]) = true.

  • إذا كان المعامل لديه ترتيب أعلى، يتم فرز المعامل وفقًا للبُعد المقدم. على سبيل المثال، بالنسبة إلى متعدّد الترتيب 2 (مصفوفة)، ستعمل قيمة البُعد 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 + 1 ببعضهما البعض، وربما يستخدم أزواجًا من المعلّمات الأخرى كقواطع ربط.

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

على سبيل المثال، إذا كان هناك ثلاثة معاملات 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 تلقائيًا على "خطأ".

تبديل

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

Transpose(operand)

الوسيطات النوع دلالات الألفاظ
operand XlaOp المعامل المراد تبديل الموضع.
permutation ArraySlice<int64> طريقة السماح للسمات

يؤدي إلى تبديل أبعاد المُعامِل مع التبديل المُعطى، وبالتالي ∀ i . 0 ≤ i < rank ⇒ input_dimensions[permutation[i]] = output_dimensions[i].

هذه الطريقة هي نفسها إعادة الشكل(العامل، التبديل، 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 أبعاد مجمّعة متساوية.

صف

يمكنك أيضًا الاطّلاع على 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};
}