این صفحه به‌وسیله ‏Cloud Translation API‏ ترجمه شده است.
Switch to English

با استفاده از کامپایل AOT

tfcompile چیست؟

tfcompile ابزاری مستقل است که قبل از زمان (AOT) نمودارهای TensorFlow را به کد اجرایی وارد می کند. این می تواند اندازه باینری کل را کاهش دهد ، همچنین از برخی از هزینه های اضافی در هنگام اجرا جلوگیری کند. یک مورد معمولی از tfcompile ، کامپایل کردن نمودار استنباط به کد قابل اجرا برای دستگاه های تلفن همراه است.

نمودار TensorFlow معمولاً توسط زمان اجرا TensorFlow انجام می شود. این برای اجرای هر گره در نمودار مقداری سربار زمان اجرا دارد. این امر همچنین به اندازه باینری بزرگتر منجر می شود ، زیرا علاوه بر خود نمودار ، کد زمان اجرا TensorFlow نیز باید موجود باشد. کد اجرایی تولید شده توسط tfcompile از زمان اجرای tfcompile استفاده نمی کند و فقط وابسته به هسته هایی است که در واقع در محاسبه استفاده می شوند.

کامپایلر در بالای چارچوب XLA ساخته شده است. پیوند کد TensorFlow به چارچوب XLA در زیر کامپایلر tensorflow / ten قرار دارد .

tfcompile چه کاری انجام می دهد؟

tfcompile یک زیرگراف را می گیرد ، که توسط مفاهیم TensorFlow فید ها و واضح ها مشخص می شود و تابعی را ایجاد می کند که آن زیرگراف را پیاده سازی می کند. feeds آرگومانهای ورودی برای عملکرد هستند و fetches آرگومانهای خروجی برای عملکرد هستند. تمام ورودی ها باید به طور کامل توسط فیدها مشخص شوند. زیرگراف هرس حاصل نمی تواند حاوی گره متغیر یا متغیر متغیر باشد. معمول است که همه متغیرهای متغیرها و متغیرها را به عنوان فید مشخص کنید ، که تضمین می کند که زیرگراف حاصل شده دیگر حاوی این گره ها نباشد. تابع تولید شده به صورت cc_library بسته می شود ، با یک فایل هدر امضای تابع و یک فایل شی حاوی پیاده سازی را صادر می کند. کاربر برای استناد به عملکرد مناسب ، کد را می نویسد.

با استفاده از tfcompile

در این بخش مراحل سطح بالا برای تولید یک باینری اجرایی با tfcompile از یک زیرگراف tfcompile . مراحل زیر است:

  • مرحله 1: برای کامپایل کردن زیرگراف را پیکربندی کنید
  • مرحله 2: برای کامپایل کردن زیرگراف از ماکرو ساخت tf_library استفاده کنید
  • مرحله 3: برای استناد به زیرنویس ، کد بنویسید
  • مرحله 4: دودویی نهایی ایجاد کنید

مرحله 1: برای کامپایل کردن زیرگراف را پیکربندی کنید

فیدها و واکشیهای مربوط به آرگومانهای ورودی و خروجی را برای عملکرد تولید شده شناسایی کنید. سپس feeds و fetches در یک tensorflow.tf2xla.Config .

 # Each feed is a positional input argument for the generated function.  The order
# of each entry matches the order of each input argument.  Here “x_hold” and “y_hold”
# refer to the names of placeholder nodes defined in the graph.
feed {
  id { node_name: "x_hold" }
  shape {
    dim { size: 2 }
    dim { size: 3 }
  }
}
feed {
  id { node_name: "y_hold" }
  shape {
    dim { size: 3 }
    dim { size: 2 }
  }
}

# Each fetch is a positional output argument for the generated function.  The order
# of each entry matches the order of each output argument.  Here “x_y_prod”
# refers to the name of a matmul node defined in the graph.
fetch {
  id { node_name: "x_y_prod" }
}
 

مرحله 2: برای کامپایل کردن زیرگراف از ماکرو ساخت tf_library استفاده کنید

این مرحله با استفاده از کلان ساخت tf_library ، نمودار را به cc_library تبدیل می کند. cc_library شامل یک پرونده شیء است که حاوی کد تولید شده از نمودار است ، به همراه یک فایل هدر که به کد تولید شده دسترسی می یابد. tf_library از tfcompile برای tfcompile نمودار tfcompile در کد اجرایی استفاده می کند.

 load("//tensorflow/compiler/aot:tfcompile.bzl", "tf_library")

# Use the tf_library macro to compile your graph into executable code.
tf_library(
    # name is used to generate the following underlying build rules:
    # <name>           : cc_library packaging the generated header and object files
    # <name>_test      : cc_test containing a simple test and benchmark
    # <name>_benchmark : cc_binary containing a stand-alone benchmark with minimal deps;
    #                    can be run on a mobile device
    name = "test_graph_tfmatmul",
    # cpp_class specifies the name of the generated C++ class, with namespaces allowed.
    # The class will be generated in the given namespace(s), or if no namespaces are
    # given, within the global namespace.
    cpp_class = "foo::bar::MatMulComp",
    # graph is the input GraphDef proto, by default expected in binary format.  To
    # use the text format instead, just use the ‘.pbtxt’ suffix.  A subgraph will be
    # created from this input graph, with feeds as inputs and fetches as outputs.
    # No Placeholder or Variable ops may exist in this subgraph.
    graph = "test_graph_tfmatmul.pb",
    # config is the input Config proto, by default expected in binary format.  To
    # use the text format instead, use the ‘.pbtxt’ suffix.  This is where the
    # feeds and fetches were specified above, in the previous step.
    config = "test_graph_tfmatmul.config.pbtxt",
)
 

برای تولید نمونه GraphDef proto (test_graph_tfmatmul.pb) برای این مثال ، make_test_graphs.py را اجرا کنید و با پرچم --out_dir محل خروجی را مشخص کنید.

نمودارهای معمولی حاوی Variables هستند که tfcompile هستند که از طریق آموزش آموخته می شوند ، اما tfcompile نمی تواند زیرگرافی را که شامل Variables کامپایل کند. ابزار freeze_graph.py با استفاده از مقادیر ذخیره شده در یک پرونده بازرسی ، متغیرها را به ثابت تبدیل می کند. به عنوان یک راحتی ، ماکرو tf_library از آرگومان freeze_checkpoint که ابزار را اجرا می کند ، پشتیبانی می کند. برای مثالهای بیشتر ، به Tensorflow / compiler / aot / test / BUILD مراجعه کنید .

ثابتهایی که در زیرگراف کامپایل شده نشان داده می شوند ، مستقیماً در کد تولید شده وارد می شوند. برای انتقال ثابت ها به جای عملکرد داخلی ، به جای اینکه آنها را کامپایل کنید ، فقط آنها را به عنوان فید عبور دهید.

برای جزئیات بیشتر در مورد کلان ساخت tf_library ، به tfcompile.bzl مراجعه کنید.

برای جزئیات بیشتر در مورد ابزار اصلی tfcompile ، به tfcompile_main.cc مراجعه کنید.

مرحله 3: برای استناد به زیرنویس ، کد بنویسید

در این مرحله از پرونده هدر ( test_graph_tfmatmul.h ) ایجاد شده توسط ماکرو ساخت tf_library در مرحله قبل برای استناد به کد تولید شده استفاده می شود. پرونده سرصفحه در دایرکتوری bazel-bin مطابق با بسته ساخت قرار گرفته است و براساس ویژگی نام تنظیم شده در کلان ساخت tf_library ساخته می شود. به عنوان مثال ، عنوان ایجاد شده برای test_graph_tfmatmul می تواند test_graph_tfmatmul.h باشد. در زیر یک نسخه مختصر از آنچه تولید می شود است. پرونده تولید شده در bazel-bin حاوی نظرات مفید دیگری است.

 namespace foo {
namespace bar {

// MatMulComp represents a computation previously specified in a
// TensorFlow graph, now compiled into executable code.
class MatMulComp {
 public:
  // AllocMode controls the buffer allocation mode.
  enum class AllocMode {
    ARGS_RESULTS_AND_TEMPS,  // Allocate arg, result and temp buffers
    RESULTS_AND_TEMPS_ONLY,  // Only allocate result and temp buffers
  };

  MatMulComp(AllocMode mode = AllocMode::ARGS_RESULTS_AND_TEMPS);
  ~MatMulComp();

  // Runs the computation, with inputs read from arg buffers, and outputs
  // written to result buffers. Returns true on success and false on failure.
  bool Run();

  // Arg methods for managing input buffers. Buffers are in row-major order.
  // There is a set of methods for each positional argument.
  void** args();

  void set_arg0_data(float* data);
  float* arg0_data();
  float& arg0(size_t dim0, size_t dim1);

  void set_arg1_data(float* data);
  float* arg1_data();
  float& arg1(size_t dim0, size_t dim1);

  // Result methods for managing output buffers. Buffers are in row-major order.
  // Must only be called after a successful Run call. There is a set of methods
  // for each positional result.
  void** results();


  float* result0_data();
  float& result0(size_t dim0, size_t dim1);
};

}  // end namespace bar
}  // end namespace foo
 

تولید C ++ کلاس فراخوانی می شود MatMulComp در foo::bar فضای نام، چرا که این بود cpp_class مشخص شده در tf_library ماکرو. تمام کلاسهای تولید شده دارای یک API مشابه هستند ، تنها تفاوت آنها روشهای کنترل بافرهای arg و نتیجه است. این روشها با توجه به تعداد و انواع بافرها ، که توسط آرگومانهای feed و fetch به کلان tf_library مشخص شده است ، tf_library .

سه نوع بافر وجود دارد که درون کلاس تولید شده اداره می شوند: args هایی که نمایانگر ورودی ها ، results نماینده خروجی ها و temps که نمایانگر بافرهای موقتی هستند که در داخل برای انجام محاسبات استفاده می شوند. به طور پیش فرض ، هر نمونه از کلاس تولید شده همه این بافرها را برای شما اختصاص داده و مدیریت می کند. آرگومان سازنده AllocMode ممکن است برای تغییر این رفتار استفاده شود. همه بافرها با مرزهای 64 بایت تراز شده اند.

کلاس C ++ تولید شده فقط یک بسته بندی در اطراف کد سطح پایین تولید شده توسط XLA است.

مثال فراخوانی عملکرد تولید شده بر اساس tfcompile_test.cc :

 #define EIGEN_USE_THREADS
#define EIGEN_USE_CUSTOM_THREAD_POOL

#include <iostream>
#include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor"
#include "tensorflow/compiler/aot/tests/test_graph_tfmatmul.h" // generated

int main(int argc, char** argv) {
  Eigen::ThreadPool tp(2);  // Size the thread pool as appropriate.
  Eigen::ThreadPoolDevice device(&tp, tp.NumThreads());


  foo::bar::MatMulComp matmul;
  matmul.set_thread_pool(&device);

  // Set up args and run the computation.
  const float args[12] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
  std::copy(args + 0, args + 6, matmul.arg0_data());
  std::copy(args + 6, args + 12, matmul.arg1_data());
  matmul.Run();

  // Check result
  if (matmul.result0(0, 0) == 58) {
    std::cout << "Success" << std::endl;
  } else {
    std::cout << "Failed. Expected value 58 at 0,0. Got:"
              << matmul.result0(0, 0) << std::endl;
  }

  return 0;
}
 

مرحله 4: دودویی نهایی ایجاد کنید

این مرحله از کتابخانه تولید شده توسط tf_library در مرحله 2 و کد نوشته شده در مرحله 3 ترکیب می کند تا یک باینری نهایی ایجاد شود. در زیر یک نمونه پرونده BUILD bazel شده است.

 # Example of linking your binary
# Also see //tensorflow/compiler/aot/tests/BUILD
load("//tensorflow/compiler/aot:tfcompile.bzl", "tf_library")

# The same tf_library call from step 2 above.
tf_library(
    name = "test_graph_tfmatmul",
    ...
)

# The executable code generated by tf_library can then be linked into your code.
cc_binary(
    name = "my_binary",
    srcs = [
        "my_code.cc",  # include test_graph_tfmatmul.h to access the generated header
    ],
    deps = [
        ":test_graph_tfmatmul",  # link in the generated object file
        "//third_party/eigen3",
    ],
    linkopts = [
          "-lpthread",
    ]
)