Pengantar Konverter Inferensi Cloud TPU v5e

Pengantar

Cloud TPU Inference Converter menyiapkan dan mengoptimalkan model TensorFlow 2 (TF2) untuk inferensi TPU. Konverter berjalan di shell VM lokal atau TPU. Shell VM TPU direkomendasikan karena sudah dilengkapi dengan alat command line yang diperlukan untuk konverter. Metode ini mengambil SavedModel yang diekspor dan melakukan langkah-langkah berikut:

  1. Konversi TPU: Menambahkan TPUPartitionedCall dan operasi TPU lainnya ke model agar dapat ditayangkan di TPU. Secara default, model yang diekspor untuk inferensi tidak memiliki operasi tersebut dan tidak dapat ditayangkan di TPU, meskipun dilatih di TPU.
  2. Pengelompokan: Menambahkan batch operasi ke model untuk mengaktifkan pengelompokan dalam grafik untuk throughput yang lebih baik.
  3. Konversi BFloat16: Pengubah ini mengonversi format data model dari float32 menjadi bfloat16 untuk mendapatkan performa komputasi yang lebih baik dan penggunaan Memori Bandwidth Tinggi (HBM) yang lebih rendah di TPU.
  4. Pengoptimalan Bentuk IO: Mengoptimalkan bentuk TensorFlow untuk data yang ditransfer antara CPU dan TPU guna meningkatkan pemanfaatan bandwidth.

Saat mengekspor model, pengguna membuat alias fungsi untuk fungsi apa pun yang ingin mereka jalankan di TPU. Adaptor ini meneruskan fungsi ini ke Pengonversi dan Pengonversi menempatkannya di TPU dan mengoptimalkannya.

Cloud TPU Inference Converter tersedia sebagai image Docker yang dapat dijalankan di lingkungan apa pun dengan Docker terinstal.

Perkiraan waktu untuk menyelesaikan langkah-langkah yang ditampilkan di atas: ~20 mnt - 30 mnt

Prasyarat

  1. Model harus berupa model TF2 dan diekspor dalam format SavedModel.
  2. Model harus memiliki alias fungsi untuk fungsi TPU. Lihat contoh kode untuk mengetahui cara melakukannya. Contoh berikut menggunakan tpu_func sebagai alias fungsi TPU.
  3. Pastikan CPU mesin Anda mendukung petunjuk Advanced Vector eXtensions (AVX), karena library Tensorflow (dependensi Cloud TPU Inference Converter) dikompilasi untuk menggunakan petunjuk AVX. Sebagian besar CPU memiliki dukungan AVX.
    1. Anda dapat menjalankan lscpu | grep avx untuk memeriksa apakah kumpulan petunjuk AVX didukung.

Sebelum memulai

Sebelum memulai penyiapan, lakukan hal berikut:

  • Buat project baru: Di Konsol Google Cloud, pada halaman pemilih project, pilih atau buat project Cloud.

  • Siapkan VM TPU: Buat VM TPU baru menggunakan Google Cloud Console atau gcloud, atau gunakan VM TPU yang ada untuk menjalankan inferensi dengan model yang dikonversi di VM TPU.

    • Pastikan image VM TPU berbasis TensorFlow. Misalnya, --version=tpu-vm-tf-2.11.0.
    • Model yang dikonversi akan dimuat dan ditayangkan di TPU VM ini.
  • Pastikan Anda memiliki alat command line yang diperlukan untuk menggunakan Cloud TPU Inference Converter. Anda dapat menginstal Google Cloud SDK dan Docker secara lokal atau menggunakan TPU VM yang menginstal software ini secara default. Anda dapat menggunakan alat-alat ini untuk berinteraksi dengan image Converter.

    Hubungkan ke instance dengan SSH menggunakan perintah berikut:

    gcloud compute tpus tpu-vm ssh ${tpu-name} --zone ${zone} --project ${project-id}
    

Penyiapan Lingkungan

Siapkan lingkungan Anda dari shell VM TPU atau dari shell lokal.

Shell VM TPU

  • Di shell VM TPU, jalankan perintah berikut untuk mengizinkan penggunaan docker non-root:

    sudo usermod -a -G docker ${USER}
    newgrp docker
    
  • Inisialisasi helper Kredensial Docker Anda:

    gcloud auth configure-docker \
      us-docker.pkg.dev
    

Shell Lokal

Di shell lokal Anda, siapkan lingkungan menggunakan langkah-langkah berikut:

  • Instal Cloud SDK, yang menyertakan alat command line gcloud.

  • Instal Docker:

  • Izinkan penggunaan Docker non-root:

    sudo usermod -a -G docker ${USER}
    newgrp docker
    
  • Login ke lingkungan Anda:

    gcloud auth login
    
  • Inisialisasi helper Kredensial Docker Anda:

    gcloud auth configure-docker \
        us-docker.pkg.dev
    
  • Tarik image Docker Konverter Inferensi:

      CONVERTER_IMAGE=us-docker.pkg.dev/cloud-tpu-images/inference/tpu-inference-converter-cli:2.13.0
      docker pull ${CONVERTER_IMAGE}
      

Gambar Konverter

Gambar ini digunakan untuk melakukan konversi model satu kali. Tetapkan jalur model dan sesuaikan opsi pengonversi agar sesuai dengan kebutuhan Anda. Bagian Contoh Penggunaan menyediakan beberapa kasus penggunaan umum.

docker run \
--mount type=bind,source=${MODEL_PATH},target=/tmp/input,readonly \
--mount type=bind,source=${CONVERTED_MODEL_PATH},target=/tmp/output \
${CONVERTER_IMAGE} \
--input_model_dir=/tmp/input \
--output_model_dir=/tmp/output \
--converter_options_string='
    tpu_functions {
      function_alias: "tpu_func"
    }
    batch_options {
      num_batch_threads: 2
      max_batch_size: 8
      batch_timeout_micros: 5000
      allowed_batch_sizes: 2
      allowed_batch_sizes: 4
      allowed_batch_sizes: 8
      max_enqueued_batches: 10
    }
'

Inferensi dengan model yang dikonversi di VM TPU

# Initialize the TPU
resolver = tf.distribute.cluster_resolver.TPUClusterResolver("local")
tf.config.experimental_connect_to_cluster(resolver)
tf.tpu.experimental.initialize_tpu_system(resolver)

# Load the model
model = tf.saved_model.load(${CONVERTED_MODEL_PATH})

# Find the signature function for serving
serving_signature = 'serving_default' # Change the serving signature if needed
serving_fn = model.signatures[serving_signature]
# Run the inference using requests.
results = serving_fn(**inputs)
logging.info("Serving results: %s", str(results))

Contoh Penggunaan

Menambahkan alias fungsi untuk fungsi TPU

  1. Temukan atau buat fungsi dalam model Anda yang menggabungkan semua yang ingin Anda jalankan di TPU. Jika @tf.function tidak ada, tambahkan.
  2. Saat menyimpan model, berikan SaveOptions seperti di bawah untuk memberi model.tpu_func alias func_on_tpu.
  3. Anda dapat meneruskan alias fungsi ini ke pengonversi.
class ToyModel(tf.keras.Model):
  @tf.function(
      input_signature=[tf.TensorSpec(shape=[None, 10], dtype=tf.float32)])
  def tpu_func(self, x):
    return x * 1.0

model = ToyModel()
save_options = tf.saved_model.SaveOptions(function_aliases={
    'func_on_tpu': model.tpu_func,
})
tf.saved_model.save(model, model_dir, options=save_options)

Mengonversi model dengan beberapa fungsi TPU

Anda dapat menempatkan beberapa fungsi di TPU. Cukup buat beberapa alias fungsi dan teruskan dalam converter_options_string ke pengonversi.

tpu_functions {
  function_alias: "tpu_func_1"
}
tpu_functions {
  function_alias: "tpu_func_2"
}

Kuantisasi

Kuantisasi adalah teknik yang mengurangi presisi angka yang digunakan untuk mewakili parameter model. Ini menghasilkan ukuran model yang lebih kecil dan komputasi yang lebih cepat. Model terkuantisasi memberikan keuntungan dalam throughput inferensi, serta penggunaan memori dan ukuran penyimpanan yang lebih kecil, dengan penurunan akurasi yang kecil.

Fitur Kuantisasi Pasca-Pelatihan baru di TensorFlow yang menargetkan TPU, dikembangkan dari fitur serupa yang sudah ada di TensorFlow Lite yang digunakan untuk menargetkan perangkat seluler dan edge. Untuk mempelajari lebih lanjut kuantisasi secara umum, Anda dapat melihat dokumen TensorFlow Lite.

Konsep kuantisasi

Bagian ini mendefinisikan konsep yang secara khusus terkait dengan kuantisasi dengan Pengonversi Inferensi.

Konsep yang terkait dengan konfigurasi TPU lainnya (misalnya, slice, host, chip, dan TensorCore) dijelaskan di halaman Arsitektur Sistem TPU.

  • Kuantisasi pasca pelatihan (PTQ): PTQ adalah teknik yang mengurangi ukuran dan kompleksitas komputasi model jaringan neural tanpa memengaruhi akurasinya secara signifikan. PTQ berfungsi dengan mengonversi bobot floating point dan aktivasi model terlatih menjadi bilangan bulat dengan presisi lebih rendah, seperti bilangan bulat 8-bit atau 16-bit. Hal ini dapat menyebabkan pengurangan ukuran model dan latensi inferensi secara signifikan, tetapi hanya mengakibatkan kerugian yang kecil pada akurasi.

  • Kalibrasi: Langkah kalibrasi untuk kuantisasi adalah proses pengumpulan statistik tentang rentang nilai yang diambil oleh bobot dan aktivasi model jaringan neural. Informasi ini digunakan untuk menentukan parameter kuantisasi model, yang merupakan nilai yang akan digunakan untuk mengonversi bobot dan aktivasi floating point menjadi bilangan bulat.

  • Set Data Representasi: Set data representatif untuk kuantisasi adalah set data kecil yang mewakili data input sebenarnya untuk model tersebut. Alat ini digunakan selama langkah kalibrasi kuantisasi untuk mengumpulkan statistik tentang rentang nilai yang akan digunakan oleh bobot dan aktivasi model. Set data representatif harus memenuhi properti berikut:

    • Elemen ini harus merepresentasikan input aktual ke model dengan benar selama inferensi. Artinya, model tersebut harus mencakup rentang nilai yang mungkin akan dilihat model di dunia nyata.
    • Jalur ini harus secara kolektif mengalir melalui setiap cabang kondisional (seperti tf.cond), jika ada. Hal ini penting karena proses kuantisasi harus dapat menangani semua input yang memungkinkan ke model, meskipun input tersebut tidak secara eksplisit diwakili dalam set data yang representatif.
    • Jenis data harus cukup besar untuk mengumpulkan statistik yang cukup dan mengurangi error. Prinsipnya, sebaiknya gunakan lebih dari 200 sampel yang representatif.

    Set data representatif dapat berupa subset dari set data pelatihan, atau dapat berupa set data terpisah yang secara khusus dirancang untuk merepresentasikan input dunia nyata pada model. Pilihan set data yang akan digunakan bergantung pada aplikasi tertentu.

  • Static Range Quantization (SRQ): SRQ menentukan rentang nilai untuk bobot dan aktivasi model jaringan neural satu kali, selama langkah kalibrasi. Ini berarti bahwa rentang nilai yang sama digunakan untuk semua input ke model. Hal ini mungkin kurang akurat dibandingkan kuantisasi rentang dinamis, terutama untuk model dengan rentang nilai input yang luas. Namun, kuantisasi rentang statis memerlukan lebih sedikit komputasi pada waktu proses dibandingkan kuantisasi rentang dinamis.

  • Kuantisasi Rentang Dinamis (DRQ): DRQ menentukan rentang nilai untuk bobot dan aktivasi model jaringan neural untuk setiap input. Hal ini memungkinkan model untuk beradaptasi dengan rentang nilai data input, yang dapat meningkatkan akurasi. Namun, kuantisasi rentang dinamis memerlukan lebih banyak komputasi pada waktu proses daripada kuantisasi rentang statis.

    Fitur Kuantisasi rentang statis Kuantisasi rentang dinamis
    Rentang nilai Ditentukan sekali, selama kalibrasi Ditentukan untuk setiap input
    Akurasi Mungkin kurang akurat, terutama untuk model dengan berbagai nilai input Dapat lebih akurat, terutama untuk model dengan berbagai nilai input
    Kompleksitas Lebih mudah Lebih sulit
    Komputasi pada waktu proses Komputasi lebih sedikit Komputasi lainnya
  • Kuantisasi khusus bobot: Kuantisasi khusus bobot adalah jenis kuantisasi yang hanya mengkuantisasi bobot model jaringan neural, sementara membiarkan aktivasi dalam floating point. Hal ini dapat menjadi pilihan yang baik untuk model yang sensitif terhadap akurasi, karena dapat membantu mempertahankan akurasi model.

Cara menggunakan kuantisasi

Kuantisasi dapat diterapkan dengan mengonfigurasi dan menetapkan QuantizationOptions ke opsi pengonversi. Opsi yang penting adalah:

  • tag: Kumpulan tag yang mengidentifikasi MetaGraphDef dalam SavedModel untuk dikuantisasi. Tidak perlu menentukan apakah Anda hanya memiliki satu MetaGraphDef.
  • signature_keys: Urutan kunci yang mengidentifikasi SignatureDef yang berisi input dan output. Jika tidak ditentukan, ["serving_default"] akan digunakan.
  • quantization_method: Metode kuantisasi yang akan diterapkan. Jika tidak ditentukan, kuantisasi STATIC_RANGE akan diterapkan.
  • op_set: Harus disimpan sebagai XLA. Saat ini, ini adalah opsi default, tidak perlu ditentukan.
  • representatif_datasets: Tentukan {i>dataset<i} yang digunakan untuk mengkalibrasi parameter kuantisasi.

Membuat {i>dataset<i} yang representatif

{i>Dataset<i} representatif pada dasarnya merupakan iterasi dari sampel. Jika sampel berupa peta: {input_key: input_value}. Contoh:

representative_dataset = [{"x": tf.random.uniform(shape=(3, 3))}
                          for _ in range(256)]

Set data representatif harus disimpan sebagai file TFRecord menggunakan class TfRecordRepresentativeDatasetSaver yang saat ini tersedia dalam paket tf-nightly pip. Contoh:

# Assumed tf-nightly installed.
import tensorflow as tf
representative_dataset = [{"x": tf.random.uniform(shape=(3, 3))}
                          for _ in range(256)]
tf.quantization.experimental.TfRecordRepresentativeDatasetSaver(
       path_map={'serving_default': '/tmp/representative_dataset_path'}
    ).save({'serving_default': representative_dataset})

Contoh

Contoh berikut mengkuantifikasi model dengan kunci tanda tangan serving_default dan alias fungsi tpu_func:

docker run \
  --mount type=bind,source=${MODEL_PATH},target=/tmp/input,readonly \
  --mount type=bind,source=${CONVERTED_MODEL_PATH},target=/tmp/output \
  ${CONVERTER_IMAGE} \
  --input_model_dir=/tmp/input \
  --output_model_dir=/tmp/output \
  --converter_options_string=' \
    tpu_functions { \
      function_alias: "tpu_func" \
    } \
    external_feature_configs { \
      quantization_options { \
        signature_keys: "serving_default" \
        representative_datasets: { \
          key: "serving_default" \
          value: { \
            tfrecord_file_path: "${TF_RECORD_FILE}" \
          } \
        } \
      } \
    } '

Menambahkan pengelompokan

Converter dapat digunakan untuk menambahkan batch ke model. Untuk deskripsi tentang opsi pengelompokan yang dapat disesuaikan, lihat Definisi opsi pengelompokan.

Secara default, Pengonversi akan mengelompokkan fungsi TPU dalam model. API ini juga dapat mengelompokkan tanda tangan dan fungsi yang diberikan pengguna yang dapat meningkatkan performa lebih lanjut. Semua fungsi TPU, fungsi yang diberikan pengguna, atau tanda tangan yang dikelompokkan, harus memenuhi persyaratan bentuk ketat operasi batch.

Konverter juga dapat memperbarui opsi pengelompokan yang ada. Berikut adalah contoh cara menambahkan batch ke model. Untuk mengetahui informasi selengkapnya tentang pengelompokan, lihat Pengelompokan mendalam.

batch_options {
  num_batch_threads: 2
  max_batch_size: 8
  batch_timeout_micros: 5000
  allowed_batch_sizes: 2
  allowed_batch_sizes: 4
  allowed_batch_sizes: 8
  max_enqueued_batches: 10
}

Menonaktifkan pengoptimalan bentuk bfloat16 dan IO

BFloat16 dan Pengoptimalan Bentuk IO diaktifkan secara default. Jika tidak cocok dengan model Anda, parameter ini dapat dinonaktifkan.

# Disable both optimizations
disable_default_optimizations: true

# Or disable them individually
io_shape_optimization: DISABLED
bfloat16_optimization: DISABLED

Laporan Konversi

Anda dapat menemukan laporan konversi ini dari log setelah menjalankan Pengonversi Inferensi. Berikut contohnya.

-------- Conversion Report --------
TPU cost of the model: 96.67% (2034/2104)
CPU cost of the model:  3.33% (70/2104)

Cost breakdown
================================
%         Cost    Name
--------------------------------
3.33      70      [CPU cost]
48.34     1017    tpu_func_1
48.34     1017    tpu_func_2
--------------------------------

Laporan ini memperkirakan biaya komputasi model output pada CPU dan TPU, lalu menguraikan lebih lanjut biaya TPU untuk setiap fungsi, yang akan mencerminkan pilihan fungsi TPU Anda pada opsi konverter.

Jika ingin memanfaatkan TPU dengan lebih baik, Anda dapat bereksperimen dengan struktur model dan menyesuaikan opsi konverter.

FAQ

Fungsi apa yang harus saya tempatkan di TPU?

Sebaiknya tempatkan sebanyak mungkin model di TPU, karena sebagian besar operasi dieksekusi lebih cepat di TPU.

Jika model Anda tidak berisi op, string, atau tensor renggang yang tidak kompatibel dengan TPU, menempatkan seluruh model pada TPU biasanya merupakan strategi terbaik. Anda juga dapat melakukannya dengan menemukan atau membuat fungsi yang menggabungkan seluruh model, membuat alias fungsi untuk model tersebut, dan meneruskannya ke Converter.

Jika model Anda berisi bagian yang tidak dapat berfungsi pada TPU (misalnya operasi, string, atau tensor sparse yang tidak kompatibel dengan TPU), pilihan fungsi TPU bergantung pada lokasi bagian yang tidak kompatibel.

  • Jika berada di awal atau akhir model, Anda dapat memfaktorkan ulang model untuk mempertahankannya di CPU. Contohnya adalah tahap pra-pemrosesan dan pasca-pemrosesan string. Untuk informasi selengkapnya tentang memindahkan kode ke CPU, lihat, "Bagaimana cara memindahkan bagian model ke CPU?" Ini menunjukkan cara umum untuk memfaktorkan ulang model.
  • Jika berada di tengah model, sebaiknya bagi model menjadi tiga bagian dan berisi semua operasi yang tidak kompatibel dengan TPU di bagian tengah, dan jalankan di CPU.
  • Jika merupakan TensorFlow renggang, pertimbangkan untuk memanggil tf.sparse.to_dense di CPU dan meneruskan TensorFlow padat yang dihasilkan ke bagian TPU model.

Faktor lain yang perlu dipertimbangkan adalah penggunaan HBM. Menyematkan tabel dapat menggunakan banyak HBM. Jika berkembang melampaui batasan hardware TPU, TPU tersebut harus ditempatkan di CPU, bersama dengan operasi pencarian.

Jika memungkinkan, hanya satu fungsi TPU yang harus ada di bawah satu tanda tangan. Jika struktur model Anda memerlukan pemanggilan beberapa fungsi TPU per permintaan inferensi yang masuk, Anda harus mengetahui adanya latensi tambahan untuk tensor pengiriman antara CPU dan TPU.

Cara yang baik untuk mengevaluasi pemilihan fungsi TPU adalah dengan memeriksa Laporan Konversi. Grafik ini menampilkan persentase komputasi yang ditempatkan di TPU, dan perincian biaya setiap fungsi TPU.

Bagaimana cara memindahkan sebagian model ke CPU?

Jika model Anda berisi bagian yang tidak dapat disalurkan di TPU, Anda harus melakukan pemfaktoran ulang model untuk memindahkannya ke CPU. Berikut adalah contoh mainan. Model ini adalah model bahasa dengan tahap pra-pemrosesan. Kode untuk definisi dan fungsi lapisan dihilangkan agar lebih praktis.

class LanguageModel(tf.keras.Model):
  @tf.function
  def model_func(self, input_string):
    word_ids = self.preprocess(input_string)
    return self.bert_layer(word_ids)

Model ini tidak dapat langsung ditayangkan di TPU karena dua alasan. Pertama, parameternya adalah string. Kedua, fungsi preprocess dapat berisi banyak operasi string. Keduanya tidak kompatibel dengan TPU.

Untuk memfaktorkan ulang model ini, Anda dapat membuat fungsi lain yang disebut tpu_func untuk menghosting bert_layer yang intensif komputasi. Kemudian, buat alias fungsi untuk tpu_func dan teruskan ke Pengonversi. Dengan cara ini, semua yang ada di dalam tpu_func akan berjalan di TPU, dan semua yang tersisa di model_func akan berjalan di CPU.

class LanguageModel(tf.keras.Model):
  @tf.function
  def tpu_func(self, word_ids):
    return self.bert_layer(word_ids)

  @tf.function
  def model_func(self, input_string):
    word_ids = self.preprocess(input_string)
    return self.tpu_func(word_ids)

Apa yang harus saya lakukan jika model memiliki operasi, string, atau TensorFlow renggang yang tidak kompatibel dengan TPU?

Sebagian besar operasi TensorFlow standar didukung di TPU, tetapi beberapa operasi yang mencakup string dan TensorFlow renggang tidak didukung. Converter tidak memeriksa operasi yang tidak kompatibel dengan TPU. Jadi, model yang berisi operasi tersebut dapat meneruskan konversi. Tetapi ketika menjalankannya untuk inferensi, error seperti di bawah ini akan terjadi.

'tf.StringToNumber' op isn't compilable for TPU device.

Jika model Anda memiliki operasi yang tidak kompatibel dengan TPU, operasi tersebut harus ditempatkan di luar fungsi TPU. Selain itu, string merupakan format data yang tidak didukung di TPU. Jadi, variabel berjenis string tidak boleh ditempatkan dalam fungsi TPU. Selain itu, parameter dan nilai yang ditampilkan dari fungsi TPU juga tidak boleh berjenis string. Demikian pula, hindari penempatan TensorFlow renggang dalam fungsi TPU termasuk dalam parameter dan nilai yang ditampilkannya.

Biasanya tidak sulit untuk memfaktorkan ulang bagian model yang tidak kompatibel dan memindahkannya ke CPU. Berikut adalah contohnya.

Bagaimana cara mendukung operasi kustom dalam model?

Jika operasi kustom digunakan dalam model Anda, Pengonversi mungkin tidak mengenalinya dan gagal mengonversi model. Hal ini karena library operasi dari pengoperasian khusus, yang berisi definisi lengkap dari pengoperasian, tidak ditautkan ke Konverter.

Karena saat ini kode pengonversi belum menjadi open source, pengonversi tidak dapat dibuat dengan op kustom.

Apa yang harus saya lakukan jika memiliki model TensorFlow 1?

Converter tidak mendukung model TensorFlow 1. Model TensorFlow 1 harus dimigrasikan ke TensorFlow 2.

Apakah saya perlu mengaktifkan bridge MLIR saat menjalankan model?

Sebagian besar model yang dikonversi dapat dijalankan dengan bridge TF2XLA MLIR yang lebih baru atau bridge TF2XLA yang asli.

Bagaimana cara mengonversi model yang telah diekspor tanpa alias fungsi?

Jika model diekspor tanpa alias fungsi, cara termudah adalah mengekspornya lagi dan membuat alias fungsi. Jika ekspor ulang tidak dapat dilakukan, model masih dapat dikonversi dengan memberikan concrete_function_name. Namun, mengidentifikasi concrete_function_name yang benar memerlukan beberapa upaya detektif.

Alias fungsi adalah pemetaan dari string buatan pengguna ke nama fungsi konkret. Mereka membuatnya lebih mudah untuk merujuk ke fungsi tertentu dalam model. Pengonversi menerima alias fungsi dan nama fungsi konkret mentah.

Nama fungsi konkret dapat ditemukan dengan memeriksa saved_model.pb.

Contoh berikut menunjukkan cara menempatkan fungsi konkret bernama __inference_serve_24 di TPU.

sudo docker run \
--mount type=bind,source=${MODEL_PATH},target=/tmp/input,readonly \
--mount type=bind,source=${CONVERTED_MODEL_PATH},target=/tmp/output \
${CONVERTER_IMAGE} \
--input_model_dir=/tmp/input \
--output_model_dir=/tmp/output \
--converter_options_string='
    tpu_functions {
      concrete_function_name: "__inference_serve_24"
    }'

Bagaimana cara mengatasi error batasan konstanta waktu kompilasi?

Untuk pelatihan dan inferensi, XLA memerlukan input ke operasi tertentu yang memiliki bentuk yang diketahui pada waktu kompilasi TPU. Artinya, saat XLA mengompilasi bagian TPU dari program, input ke operasi tersebut harus memiliki bentuk yang diketahui secara statis.

Ada dua cara untuk mengatasi masalah ini.

  • Opsi terbaik adalah mengupdate input operasi agar memiliki bentuk yang diketahui secara statis pada saat XLA mengompilasi program TPU. Kompilasi ini terjadi tepat sebelum bagian TPU dari model dijalankan. Ini berarti bentuk harus diketahui secara statis pada saat TpuFunction akan berjalan.
  • Opsi lainnya adalah memodifikasi TpuFunction agar tidak lagi menyertakan op yang bermasalah.

Mengapa saya mendapatkan error bentuk batch?

Pengelompokan memiliki persyaratan bentuk ketat yang memungkinkan permintaan masuk dikelompokkan di sepanjang dimensi ke-0 (alias dimensi batch). Persyaratan bentuk ini berasal dari operasi batching TensorFlow dan tidak dapat disesuaikan.

Kegagalan dalam memenuhi persyaratan ini akan mengakibatkan error seperti:

  1. Pengelompokan_tensor input harus memiliki setidaknya satu dimensi.
  2. Dimensi input harus cocok.
  3. Tensor input batch yang disediakan dalam pemanggilan operasi tertentu harus memiliki ukuran dimensi ke-0 yang sama.
  4. Dimensi ke-0 Tensor output batch tidak sama dengan jumlah ukuran dimensi ke-0 dari TensorFlow input.

Untuk memenuhi persyaratan ini, pertimbangkan untuk menyediakan fungsi atau tanda tangan lain ke batch. Anda mungkin juga perlu memodifikasi fungsi yang ada agar memenuhi persyaratan ini.

Jika fungsi dikelompokkan, pastikan semua bentuk input_signature @tf.function-nya memiliki nilai None (Tidak ada) di dimensi ke-0. Jika tanda tangan dikelompokkan, pastikan semua inputnya memiliki angka -1 dalam dimensi ke-0.

Untuk penjelasan lengkap tentang alasan terjadinya error ini dan cara mengatasinya, lihat Pengelompokan Mendalam.

Masalah Umum

Fungsi TPU tidak dapat memanggil fungsi TPU lainnya secara tidak langsung

Meskipun Pengonversi dapat menangani sebagian besar skenario pemanggilan fungsi di seluruh batas CPU-TPU, ada satu kasus ekstrem yang jarang terjadi yang akan gagal. Ini terjadi saat fungsi TPU secara tidak langsung memanggil fungsi TPU lainnya.

Hal ini karena Pengonversi mengubah pemanggil langsung fungsi TPU dari memanggil fungsi TPU itu sendiri menjadi memanggil stub panggilan TPU. stub panggilan berisi operasi yang hanya dapat bekerja pada CPU. Saat fungsi TPU memanggil fungsi apa pun yang pada akhirnya memanggil pemanggil langsung, operasi CPU tersebut dapat dibawa ke TPU untuk dijalankan, sehingga akan menghasilkan error kernel yang tidak ada. Perhatikan bahwa kasus ini berbeda dengan fungsi TPU yang langsung memanggil fungsi TPU lainnya. Dalam hal ini, Converter tidak mengubah fungsi mana pun untuk memanggil stub panggilan, sehingga dapat berfungsi.

Di Converter, kita telah mengimplementasikan deteksi skenario ini. Jika Anda melihat error berikut, artinya model Anda telah mencapai kasus ekstrem ini:

Unable to place both "__inference_tpu_func_2_46" and "__inference_tpu_func_4_68"
on the TPU because "__inference_tpu_func_2_46" indirectly calls
"__inference_tpu_func_4_68". This behavior is unsupported because it can cause
invalid graphs to be generated.

Solusi umumnya adalah dengan memfaktorkan ulang model untuk menghindari fungsi yang memanggil skenario. Jika Anda merasa hal itu sulit dilakukan, hubungi tim dukungan Google untuk mendiskusikan lebih lanjut.

Referensi

Opsi Converter dalam format Protobuf

message ConverterOptions {
  // TPU conversion options.
  repeated TpuFunction tpu_functions = 1;

  // The state of an optimization.
  enum State {
    // When state is set to default, the optimization will perform its
    // default behavior. For some optimizations this is disabled and for others
    // it is enabled. To check a specific optimization, read the optimization's
    // description.
    DEFAULT = 0;
    // Enabled.
    ENABLED = 1;
    // Disabled.
    DISABLED = 2;
  }

  // Batch options to apply to the TPU Subgraph.
  //
  // At the moment, only one batch option is supported. This field will be
  // expanded to support batching on a per function and/or per signature basis.
  //
  //
  // If not specified, no batching will be done.
  repeated BatchOptions batch_options = 100;

  // Global flag to disable all optimizations that are enabled by default.
  // When enabled, all optimizations that run by default are disabled. If a
  // default optimization is explicitly enabled, this flag will have no affect
  // on that optimization.
  //
  // This flag defaults to false.
  bool disable_default_optimizations = 202;

  // If enabled, apply an optimization that reshapes the tensors going into
  // and out of the TPU. This reshape operation improves performance by reducing
  // the transfer time to and from the TPU.
  //
  // This optimization is incompatible with input_shape_opt which is disabled.
  // by default. If input_shape_opt is enabled, this option should be
  // disabled.
  //
  // This optimization defaults to enabled.
  State io_shape_optimization = 200;

  // If enabled, apply an optimization that updates float variables and float
  // ops on the TPU to bfloat16. This optimization improves performance and
  // throughtput by reducing HBM usage and taking advantage of TPU support for
  // bfloat16.
  //
  // This optimization may cause a loss of accuracy for some models. If an
  // unacceptable loss of accuracy is detected, disable this optimization.
  //
  // This optimization defaults to enabled.
  State bfloat16_optimization = 201;

  BFloat16OptimizationOptions bfloat16_optimization_options = 203;

  // The settings for XLA sharding. If set, XLA sharding is enabled.
  XlaShardingOptions xla_sharding_options = 204;
}

message TpuFunction {
  // The function(s) that should be placed on the TPU. Only provide a given
  // function once. Duplicates will result in errors. For example, if
  // you provide a specific function using function_alias don't also provide the
  // same function via concrete_function_name or jit_compile_functions.
  oneof name {
    // The name of the function alias associated with the function that
    // should be placed on the TPU. Function aliases are created during model
    // export using the tf.saved_model.SaveOptions.
    //
    // This is a recommended way to specify which function should be placed
    // on the TPU.
    string function_alias = 1;

    // The name of the concrete function that should be placed on the TPU. This
    // is the name of the function as it found in the GraphDef and the
    // FunctionDefLibrary.
    //
    // This is NOT the recommended way to specify which function should be
    // placed on the TPU because concrete function names change every time a
    // model is exported.
    string concrete_function_name = 3;

    // The name of the signature to be placed on the TPU. The user must make
    // sure there is no TPU-incompatible op under the entire signature.
    string signature_name = 5;

    // When jit_compile_functions is set to True, all jit compiled functions
    // are placed on the TPU.
    //
    // To use this option, decorate the relevant function(s) with
    // @tf.function(jit_compile=True), before exporting. Then set this flag to
    // True. The converter will find all functions that were tagged with
    // jit_compile=True and place them on the TPU.
    //
    // When using this option, all other settings for the TpuFunction
    // will apply to all functions tagged with
    // jit_compile=True.
    //
    // This option will place all jit_compile=True functions on the TPU.
    // If only some jit_compile=True functions should be placed on the TPU,
    // use function_alias or concrete_function_name.
    bool jit_compile_functions = 4;
  }

}

message BatchOptions {
  // Number of scheduling threads for processing batches of work. Determines
  // the number of batches processed in parallel. This should be roughly in line
  // with the number of TPU cores available.
  int32 num_batch_threads = 1;

  // The maximum allowed batch size.
  int32 max_batch_size = 2;

  // Maximum number of microseconds to wait before outputting an incomplete
  // batch.
  int32 batch_timeout_micros = 3;

  // Optional list of allowed batch sizes. If left empty,
  // does nothing. Otherwise, supplies a list of batch sizes, causing the op
  // to pad batches up to one of those sizes. The entries must increase
  // monotonically, and the final entry must equal max_batch_size.
  repeated int32 allowed_batch_sizes = 4;

  // Maximum number of batches enqueued for processing before requests are
  // failed fast.
  int32 max_enqueued_batches = 5;

  // If set, disables large batch splitting which is an efficiency improvement
  // on batching to reduce padding inefficiency.
  bool disable_large_batch_splitting = 6;

  // Experimental features of batching. Everything inside is subject to change.
  message Experimental {
    // The component to be batched.
    // 1. Unset if it's for all TPU subgraphs.
    // 2. Set function_alias or concrete_function_name if it's for a function.
    // 3. Set signature_name if it's for a signature.
    oneof batch_component {
      // The function alias associated with the function. Function alias is
      // created during model export using the tf.saved_model.SaveOptions, and is
      // the recommended way to specify functions.
      string function_alias = 1;

      // The concreate name of the function. This is the name of the function as
      // it found in the GraphDef and the FunctionDefLibrary. This is NOT the
      // recommended way to specify functions, because concrete function names
      // change every time a model is exported.
      string concrete_function_name = 2;

      // The name of the signature.
      string signature_name = 3;
    }
  }

  Experimental experimental = 7;
}

message BFloat16OptimizationOptions {
  // Indicates where the BFloat16 optimization should be applied.
  enum Scope {
    // The scope currently defaults to TPU.
    DEFAULT = 0;
    // Apply the bfloat16 optimization to TPU computation.
    TPU = 1;
    // Apply the bfloat16 optimization to the entire model including CPU
    // computations.
    ALL = 2;
  }

  // This field indicates where the bfloat16 optimization should be applied.
  //
  // The scope defaults to TPU.
  Scope scope = 1;

  // If set, the normal safety checks are skipped. For example, if the model
  // already contains bfloat16 ops, the bfloat16 optimization will error because
  // pre-existing bfloat16 ops can cause issues with the optimization. By
  // setting this flag, the bfloat16 optimization will skip the check.
  //
  // This is an advanced feature and not recommended for almost all models.
  //
  // This flag is off by default.
  bool skip_safety_checks = 2;

  // Ops that should not be converted to bfloat16.
  // Inputs into these ops will be cast to float32, and outputs from these ops
  // will be cast back to bfloat16.
  repeated string filterlist = 3;
}

message XlaShardingOptions {
  // num_cores_per_replica for TPUReplicateMetadata.
  //
  // This is the number of cores you wish to split your model into using XLA
  // SPMD.
  int32 num_cores_per_replica = 1;

  // (optional) device_assignment for TPUReplicateMetadata.
  //
  // This is in a flattened [x, y, z, core] format (for
  // example, core 1 of the chip
  // located in 2,3,0 will be stored as [2,3,0,1]).
  //
  // If this is not specified, then the device assignments will utilize the same
  // topology as specified in the topology attribute.
  repeated int32 device_assignment = 2;

  // A serialized string of tensorflow.tpu.TopologyProto objects, used for
  // the topology attribute in TPUReplicateMetadata.
  //
  // You must specify the mesh_shape and device_coordinates attributes in
  // the topology object.
  //
  // This option is required for num_cores_per_replica > 1 cases due to
  // ambiguity of num_cores_per_replica, for example,
  // pf_1x2x1 with megacore and df_1x1
  // both have num_cores_per_replica = 2, but topology is (1,2,1,1) for pf and
  // (1,1,1,2) for df.
  // - For pf_1x2x1, mesh shape and device_coordinates looks like:
  //   mesh_shape = [1,2,1,1]
  //   device_coordinates=flatten([0,0,0,0], [0,1,0,0])
  // - For df_1x1, mesh shape and device_coordinates looks like:
  //   mesh_shape = [1,1,1,2]
  //   device_coordinates=flatten([0,0,0,0], [0,0,0,1])
  // - For df_2x2, mesh shape and device_coordinates looks like:
  //   mesh_shape = [2,2,1,2]
  //   device_coordinates=flatten(
  //    [0,0,0,0],[0,0,0,1],[0,1,0,0],[0,1,0,1]
  //    [1,0,0,0],[1,0,0,1],[1,1,0,0],[1,1,0,1])
  bytes topology = 3;
}

Pembahasan Mendalam

Pengelompokan digunakan untuk meningkatkan throughput dan pemanfaatan TPU. Metode ini memungkinkan beberapa permintaan diproses secara bersamaan. Selama pelatihan, pengelompokan dapat dilakukan menggunakan tf.data. Selama inferensi, hal ini biasanya dilakukan dengan menambahkan operasi dalam grafik yang mengelompokkan permintaan masuk. Operasi menunggu hingga memiliki permintaan yang cukup atau waktu tunggu tercapai sebelum menghasilkan batch besar dari permintaan individual. Lihat Definisi opsi pengelompokan untuk mengetahui informasi selengkapnya tentang berbagai opsi pengelompokan yang dapat disesuaikan, termasuk ukuran tumpukan dan waktu tunggu.

pengelompokan dalam grafik

Secara default, Pengonversi menyisipkan batching op langsung sebelum komputasi TPU. Solusi ini menggabungkan fungsi TPU yang diberikan pengguna dan komputasi TPU yang sudah ada sebelumnya dalam model dengan batch operasi. Anda dapat mengganti perilaku default ini dengan memberi tahu Pengonversi fungsi dan/atau tanda tangan mana yang harus dikelompokkan.

Contoh berikut menunjukkan cara menambahkan pengelompokan default.

batch_options {
  num_batch_threads: 2
  max_batch_size: 8
  batch_timeout_micros: 5000
  allowed_batch_sizes: 2
  allowed_batch_sizes: 4
  allowed_batch_sizes: 8
  max_enqueued_batches: 10
}

Pengelompokan tanda tangan

Pengelompokan tanda tangan mengelompokkan seluruh model mulai dari input tanda tangan dan mengarah ke output tanda tangan. Tidak seperti perilaku pengelompokan default Pengonversi, pengelompokan tanda tangan mengelompokkan komputasi TPU dan komputasi CPU. Ini memberikan peningkatan performa 10% hingga 20% selama inferensi pada beberapa model.

Seperti semua pengelompokan, pengelompokan tanda tangan memiliki persyaratan bentuk yang ketat. Untuk membantu memastikan persyaratan bentuk ini terpenuhi, input tanda tangan harus memiliki bentuk yang memiliki setidaknya dua dimensi. Dimensi pertama adalah ukuran tumpukan dan harus memiliki ukuran -1. Misalnya, (-1, 4), (-1), atau (-1, 128, 4, 10) adalah bentuk input yang valid. Jika tidak memungkinkan, pertimbangkan untuk menggunakan perilaku pengelompokan default atau pengelompokan fungsi.

Untuk menggunakan pengelompokan tanda tangan, berikan nama tanda tangan sebagai signature_name menggunakan BatchOptions.

batch_options {
  num_batch_threads: 2
  max_batch_size: 8
  batch_timeout_micros: 5000
  allowed_batch_sizes: 2
  allowed_batch_sizes: 4
  allowed_batch_sizes: 8
  max_enqueued_batches: 10
  experimental {
    signature_name: "serving_default"
  }
}

Pengelompokan fungsi

Pengelompokan fungsi dapat digunakan untuk memberi tahu Pengonversi fungsi mana yang harus dikelompokkan. Secara default, Pengonversi akan mengelompokkan semua fungsi TPU. Pengelompokan fungsi akan menggantikan perilaku default ini.

Pengelompokan fungsi dapat digunakan untuk melakukan batch komputasi CPU. Banyak model mengalami peningkatan performa saat komputasi CPU mereka dikelompokkan. Cara terbaik untuk mengelompokkan komputasi CPU adalah menggunakan pengelompokan tanda tangan, tetapi cara ini mungkin tidak berfungsi untuk beberapa model. Dalam kasus tersebut, selain komputasi TPU, pengelompokan fungsi dapat digunakan untuk mengelompokkan bagian dari komputasi CPU. Perlu diperhatikan bahwa batching op tidak dapat dijalankan di TPU, sehingga fungsi pengelompokan apa pun yang disediakan harus dipanggil di CPU.

Pengelompokan fungsi juga dapat digunakan untuk memenuhi persyaratan bentuk ketat yang diberlakukan oleh batching op. Jika fungsi TPU tidak memenuhi persyaratan bentuk batching op, pengelompokan fungsi dapat digunakan untuk memberi tahu Pengonversi untuk mengelompokkan fungsi yang berbeda.

Untuk menggunakan ini, buat function_alias untuk fungsi yang harus dikelompokkan. Anda dapat melakukannya dengan menemukan atau membuat fungsi dalam model yang menggabungkan semua yang ingin Anda kelompokkan. Pastikan fungsi ini memenuhi persyaratan bentuk ketat yang diberlakukan oleh operasi batch. Tambahkan @tf.function jika belum memilikinya. Penting untuk memberikan input_signature ke @tf.function. Dimensi ke-0 harus None karena merupakan dimensi batch sehingga tidak boleh berupa ukuran tetap. Misalnya, [None, 4], [None], atau [None, 128, 4, 10] adalah bentuk input yang valid. Saat menyimpan model, berikan SaveOptions seperti yang ditunjukkan di bawah untuk memberi model.batch_func alias "batch_func". Kemudian, Anda dapat meneruskan alias fungsi ini ke pengonversi.

class ToyModel(tf.keras.Model):
  @tf.function(input_signature=[tf.TensorSpec(shape=[None, 10],
                                              dtype=tf.float32)])
  def batch_func(self, x):
    return x * 1.0

  ...

model = ToyModel()
save_options = tf.saved_model.SaveOptions(function_aliases={
    'batch_func': model.batch_func,
})
tf.saved_model.save(model, model_dir, options=save_options)

Selanjutnya, teruskan function_alias menggunakan BatchOptions.

batch_options {
  num_batch_threads: 2
  max_batch_size: 8
  batch_timeout_micros: 5000
  allowed_batch_sizes: 2
  allowed_batch_sizes: 4
  allowed_batch_sizes: 8
  max_enqueued_batches: 10
  experimental {
    function_alias: "batch_func"
  }
}

Definisi opsi pengelompokan

  • num_batch_threads: (bilangan bulat) Jumlah thread penjadwalan untuk memproses batch tugas. Menentukan jumlah batch yang diproses secara paralel. Jumlah ini seharusnya hampir sama dengan jumlah core TPU yang tersedia.
  • max_batch_size: (bilangan bulat) Ukuran tumpukan maksimum yang diizinkan. Dapat lebih besar dari allowed_batch_sizes untuk memanfaatkan pemisahan batch besar.
  • batch_timeout_micros: (bilangan bulat) Jumlah mikrodetik maksimum untuk ditunggu sebelum menghasilkan output batch yang tidak lengkap.
  • allowed_batch_sizes: (daftar bilangan bulat) Jika daftar tidak kosong, daftar akan menumpuk ke ukuran terdekat dalam daftar. Daftar harus meningkat secara monoton dan elemen akhir harus lebih rendah dari atau sama dengan max_batch_size.
  • max_enqueued_batches: (bilangan bulat) Jumlah maksimum batch yang diantrekan untuk diproses sebelum permintaan gagal dengan cepat.

Memperbarui opsi pengelompokan yang ada

Anda dapat menambahkan atau memperbarui opsi pengelompokan dengan menjalankan image Docker yang menentukan batch_options dan menetapkan disable_default_optimizations ke benar menggunakan flag --converter_options_string. Opsi batch akan diterapkan ke setiap fungsi TPU atau operasi batch yang sudah ada.

batch_options {
  num_batch_threads: 2
  max_batch_size: 8
  batch_timeout_micros: 5000
  allowed_batch_sizes: 2
  allowed_batch_sizes: 4
  allowed_batch_sizes: 8
  max_enqueued_batches: 10
}
disable_default_optimizations=True

Persyaratan bentuk pengelompokan

Batch dibuat dengan menggabungkan TensorFlow input di seluruh permintaan di sepanjang dimensi batch (ke-0). Tensor output dibagi di sepanjang dimensi ke-0. Untuk menjalankan operasi ini, batching op memiliki persyaratan bentuk yang ketat untuk input dan output-nya.

Panduan

Untuk memahami persyaratan ini, sebaiknya pahami terlebih dahulu bagaimana pengelompokan dilakukan. Dalam contoh di bawah, kita mengelompokkan op tf.matmul sederhana.

def my_func(A, B)
    return tf.matmul(A, B)

Permintaan inferensi pertama menghasilkan input A dan B dengan bentuk (1, 3, 2) dan (1, 2, 4) masing-masing. Permintaan inferensi kedua menghasilkan input A dan B dengan bentuk (2, 3, 2) dan (2, 2, 4).

permintaan inferensi 1

Waktu tunggu pengelompokan tercapai. Model ini mendukung ukuran batch 3 sehingga permintaan inferensi #1 dan #2 dikelompokkan bersama tanpa padding. Tensor batch dibentuk dengan menggabungkan permintaan #1 dan #2 di sepanjang dimensi batch (0). Karena A #1 memiliki bentuk (1, 3, 2) dan A #2 memiliki bentuk (2, 3, 2), jika digabungkan di sepanjang dimensi batch (0), bentuk yang dihasilkan adalah (3, 3, 2).

permintaan batch

tf.matmul dieksekusi dan menghasilkan output dengan bentuk (3, 3, 4).

permintaan matmul batch

Output tf.matmul dikelompokkan sehingga harus dibagi kembali menjadi permintaan terpisah. Operasi batching melakukannya dengan melakukan pemisahan di sepanjang dimensi batch (0) dari setiap TensorFlow output. Atribut ini memutuskan cara membagi dimensi ke-0 berdasarkan bentuk input asli. Karena bentuk permintaan #1 memiliki dimensi ke-0 dari 1, output-nya memiliki dimensi ke-0 bernilai 1 untuk bentuk (1, 3, 4). Karena bentuk permintaan #2 memiliki dimensi ke-0 dari 2, outputnya memiliki dimensi 0 dengan 2 untuk bentuk (2, 3, 4).

hasil permintaan inferensi

Persyaratan Bentuk

Untuk melakukan penggabungan input dan pemisahan output yang dijelaskan di atas, batching op memiliki persyaratan bentuk berikut:

  1. Input untuk pengelompokan tidak boleh berupa skalar. Untuk menyambungkan di sepanjang dimensi ke-0, TensorFlow harus memiliki setidaknya dua dimensi.

    Dalam panduan di atas. Baik A maupun B bukan skalar.

    Kegagalan dalam memenuhi persyaratan ini akan menyebabkan error seperti: Batching input tensors must have at least one dimension. Perbaikan sederhana untuk kesalahan ini adalah dengan membuat skalar menjadi vektor.

  2. Di berbagai permintaan inferensi yang berbeda (misalnya, Pemanggilan run Sesi yang berbeda), Tensor input dengan nama yang sama memiliki ukuran yang sama untuk setiap dimensi kecuali dimensi ke-0. Hal ini memungkinkan {i>input<i} untuk digabungkan dengan rapi di sepanjang dimensi ke-0.

    Dalam panduan di atas, permintaan A #1 memiliki bentuk (1, 3, 2). Ini berarti setiap permintaan berikutnya harus menghasilkan bentuk dengan pola (X, 3, 2). Permintaan #2 memenuhi persyaratan ini dengan (2, 3, 2). Demikian pula, permintaan #1 B memiliki bentuk (1, 2, 4) sehingga semua permintaan berikutnya harus menghasilkan bentuk dengan pola (X, 2, 4).

    Kegagalan dalam memenuhi persyaratan ini akan menyebabkan error seperti: Dimensions of inputs should match.

  3. Untuk permintaan inferensi tertentu, semua input harus memiliki ukuran dimensi ke-0 yang sama. Jika TensorFlow yang berbeda dengan batching op memiliki dimensi ke-0 yang berbeda, batching op tidak akan mengetahui cara membagi TensorFlow output.

    Pada panduan di atas, semua TensorFlow permintaan #1 memiliki ukuran dimensi ke-0 sebesar 1. Dengan begitu, batching op dapat mengetahui bahwa outputnya harus memiliki ukuran dimensi ke-0 sebesar 1. Demikian pula, Tensor #2 memiliki ukuran dimensi 0 sebesar 2, sehingga output-nya akan memiliki ukuran dimensi ke-0 sebesar 2. Saat batching op membagi bentuk akhir (3, 3, 4), ini menghasilkan (1, 3, 4) untuk permintaan #1 dan (2, 3, 4) untuk permintaan #2.

    Kegagalan dalam memenuhi persyaratan ini akan mengakibatkan error seperti: Batching input tensors supplied in a given op invocation must have equal 0th-dimension size.

  4. Ukuran dimensi ke-0 dari setiap bentuk TensorFlow output harus merupakan jumlah dari semua ukuran dimensi ke-0 TensorFlow (ditambah padding yang diperkenalkan oleh batching op untuk memenuhi allowed_batch_size terbesar berikutnya). Hal ini memungkinkan batching op untuk membagi TensorFlow output di sepanjang dimensi ke-0 berdasarkan dimensi ke-0 dari TensorFlow input.

    Pada panduan di atas, Tensor input memiliki dimensi ke-0 1 dari permintaan #1 dan 2 dari permintaan #2. Oleh karena itu, setiap TensorFlow output harus memiliki dimensi ke-0 3 karena 1+2=3. Tensor output (3, 3, 4) memenuhi persyaratan ini. Jika 3 bukanlah ukuran tumpukan yang valid, tetapi 4 adalah ukuran tumpukan, operasi batch harus menambahkan dimensi ke-0 dari input dari 3 menjadi 4. Dalam hal ini, setiap TensorFlow output harus memiliki ukuran dimensi ke-0 sebesar 4.

    Kegagalan dalam memenuhi persyaratan ini akan menyebabkan error seperti: Batched output tensor's 0th dimension does not equal the sum of the 0th dimension sizes of the input tensors.

Menyelesaikan Error Persyaratan Bentuk

Untuk memenuhi persyaratan ini, pertimbangkan untuk menyediakan fungsi atau tanda tangan lain ke batch. Anda mungkin juga perlu memodifikasi fungsi yang ada agar memenuhi persyaratan ini.

Jika fungsi dikelompokkan, pastikan bentuk input_signature @tf.function-nya semua memiliki None dalam dimensi ke-0 (alias dimensi batch). Jika tanda tangan dikelompokkan, pastikan semua inputnya memiliki angka -1 dalam dimensi ke-0.

Operasi BatchFunction tidak mendukung SparseTensors sebagai input atau output. Secara internal, setiap5_tensor renggang direpresentasikan sebagai tiga tensor terpisah yang dapat memiliki ukuran dimensi ke-0 yang berbeda.