TensorFlow প্রোফাইলারের সাথে TensorFlow GPU পারফরম্যান্স অপ্টিমাইজ করুন

ওভারভিউ

এই নির্দেশিকাটি আপনাকে দেখাবে কিভাবে TensorBoard-এর সাথে TensorFlow প্রোফাইলার ব্যবহার করতে হয় এবং আপনার GPU গুলির মধ্যে অন্তর্দৃষ্টি পেতে এবং সর্বাধিক কার্যক্ষমতা পেতে এবং আপনার এক বা একাধিক GPU গুলি কম ব্যবহার করা হলে ডিবাগ করতে হবে৷

আপনি যদি প্রোফাইলারে নতুন হন:

মনে রাখবেন যে GPU তে কম্পিউটেশন অফলোড করা সবসময় উপকারী নাও হতে পারে, বিশেষ করে ছোট মডেলের জন্য। এর কারণে ওভারহেড থাকতে পারে:

  • হোস্ট (CPU) এবং ডিভাইসের (GPU) মধ্যে ডেটা স্থানান্তর; এবং
  • হোস্ট যখন GPU কার্নেল চালু করে তখন জড়িত বিলম্বের কারণে।

কর্মক্ষমতা অপ্টিমাইজেশান কর্মপ্রবাহ

এই নির্দেশিকাটি একটি একক GPU দিয়ে শুরু করে, তারপর একাধিক GPU সহ একটি একক হোস্টে কীভাবে কর্মক্ষমতা সমস্যাগুলি ডিবাগ করতে হয় তার রূপরেখা দেয়৷

নিম্নলিখিত ক্রমে কর্মক্ষমতা সমস্যা ডিবাগ করার সুপারিশ করা হয়:

  1. একটি জিপিইউতে কর্মক্ষমতা অপ্টিমাইজ এবং ডিবাগ করুন:
    1. ইনপুট পাইপলাইন একটি বাধা কিনা পরীক্ষা করুন.
    2. একটি GPU-এর কর্মক্ষমতা ডিবাগ করুন।
    3. মিশ্র নির্ভুলতা সক্ষম করুন ( fp16 (float16) সহ) এবং ঐচ্ছিকভাবে XLA সক্ষম করুন৷
  2. মাল্টি-জিপিইউ একক হোস্টে কর্মক্ষমতা অপ্টিমাইজ এবং ডিবাগ করুন।

উদাহরণস্বরূপ, আপনি যদি একাধিক GPU সহ একটি একক হোস্টে একটি মডেলকে প্রশিক্ষণ দেওয়ার জন্য একটি TensorFlow বিতরণ কৌশল ব্যবহার করেন এবং সাবঅপ্টিমাল GPU ব্যবহার লক্ষ্য করেন, তাহলে আপনাকে মাল্টি-GPU সিস্টেম ডিবাগ করার আগে প্রথমে একটি GPU-এর কর্মক্ষমতা অপ্টিমাইজ এবং ডিবাগ করা উচিত।

GPU-তে পারফরম্যান্ট কোড পাওয়ার জন্য একটি বেসলাইন হিসাবে, এই গাইডটি ধরে নেয় আপনি ইতিমধ্যেই tf.function ব্যবহার করছেন। Keras Model.compile এবং Model.fit APIগুলি হুডের নীচে স্বয়ংক্রিয়ভাবে tf.function ব্যবহার করবে৷ tf.GradientTape এর সাথে একটি কাস্টম প্রশিক্ষণ লুপ লেখার সময়, tf.function s কীভাবে সক্ষম করা যায় সে সম্পর্কে tf.function সহ আরও ভাল পারফরম্যান্স দেখুন।

পরবর্তী বিভাগগুলি পারফরম্যান্সের প্রতিবন্ধকতা চিহ্নিত করতে এবং ঠিক করতে সাহায্য করার জন্য উপরের প্রতিটি পরিস্থিতির জন্য প্রস্তাবিত পন্থা নিয়ে আলোচনা করে।

1. একটি GPU-তে কর্মক্ষমতা অপ্টিমাইজ করুন

একটি আদর্শ ক্ষেত্রে, আপনার প্রোগ্রামে উচ্চ GPU ব্যবহার, ন্যূনতম CPU (হোস্ট) থেকে GPU (ডিভাইস) যোগাযোগ থাকা উচিত এবং ইনপুট পাইপলাইন থেকে কোনও ওভারহেড থাকা উচিত নয়।

কর্মক্ষমতা বিশ্লেষণের প্রথম ধাপ হল একটি GPU সহ চলমান মডেলের জন্য একটি প্রোফাইল পাওয়া।

TensorBoard এর প্রোফাইলার ওভারভিউ পৃষ্ঠা — যা আপনার মডেলটি প্রোফাইল চালানোর সময় কীভাবে পারফর্ম করেছে তার একটি শীর্ষ স্তরের ভিউ দেখায় — আপনার প্রোগ্রামটি আদর্শ পরিস্থিতি থেকে কতটা দূরে তা একটি ধারণা প্রদান করতে পারে।

TensorFlow Profiler Overview Page

ওভারভিউ পৃষ্ঠায় মনোযোগ দিতে মূল সংখ্যাগুলি হল:

  1. প্রকৃত ডিভাইস এক্সিকিউশন থেকে স্টেপ টাইম কত
  2. ডিভাইস বনাম হোস্টে স্থাপন করা অপারেশনের শতাংশ
  3. কত কার্নেল fp16 ব্যবহার করে

সর্বোত্তম কর্মক্ষমতা অর্জনের অর্থ হল তিনটি ক্ষেত্রেই এই সংখ্যাগুলিকে সর্বাধিক করা৷ আপনার প্রোগ্রামের গভীরভাবে বোঝার জন্য, আপনাকে টেনসরবোর্ডের প্রোফাইলার ট্রেস ভিউয়ারের সাথে পরিচিত হতে হবে। নীচের বিভাগগুলি কিছু সাধারণ ট্রেস ভিউয়ার প্যাটার্ন দেখায় যা আপনার কর্মক্ষমতা বাধা নির্ণয় করার সময় সন্ধান করা উচিত।

নীচে একটি জিপিইউতে চলমান একটি মডেল ট্রেস ভিউয়ের একটি চিত্র রয়েছে৷ TensorFlow Name Scope এবং TensorFlow Ops বিভাগ থেকে, আপনি মডেলের বিভিন্ন অংশ শনাক্ত করতে পারেন, যেমন ফরোয়ার্ড পাস, লস ফাংশন, ব্যাকওয়ার্ড পাস/গ্রেডিয়েন্ট ক্যালকুলেশন, এবং অপ্টিমাইজার ওজন আপডেট। আপনি প্রতিটি স্ট্রীমের পাশের GPU-তে অপ্স চালু রাখতে পারেন, যা CUDA স্ট্রীমকে উল্লেখ করে। প্রতিটি স্ট্রীম নির্দিষ্ট কাজের জন্য ব্যবহৃত হয়। এই ট্রেসে, স্ট্রিম#118 কম্পিউট কার্নেল এবং ডিভাইস থেকে ডিভাইস কপি চালু করতে ব্যবহৃত হয়। স্ট্রিম#119 হোস্ট-টু-ডিভাইস কপির জন্য এবং স্ট্রীম#120 ডিভাইসের কপি হোস্ট করার জন্য ব্যবহার করা হয়।

নীচের ট্রেসটি একটি পারফরম্যান্ট মডেলের সাধারণ বৈশিষ্ট্যগুলি দেখায়৷

image

উদাহরণস্বরূপ, GPU কম্পিউট টাইমলাইন ( Stream#118 ) খুব কম ফাঁকে "ব্যস্ত" দেখায়। হোস্ট থেকে ডিভাইস ( স্ট্রিম #119 ) এবং ডিভাইস থেকে হোস্ট ( স্ট্রিম #120 ) পর্যন্ত ন্যূনতম কপি রয়েছে, পাশাপাশি ধাপগুলির মধ্যে ন্যূনতম ব্যবধান রয়েছে। আপনি যখন আপনার প্রোগ্রামের জন্য প্রোফাইলার চালান, তখন আপনি আপনার ট্রেস ভিউতে এই আদর্শ বৈশিষ্ট্যগুলি সনাক্ত করতে পারবেন না। এই গাইডের বাকি অংশে সাধারণ পরিস্থিতি এবং সেগুলি কীভাবে ঠিক করা যায় তা কভার করে।

1. ইনপুট পাইপলাইন ডিবাগ করুন

GPU পারফরম্যান্স ডিবাগিংয়ের প্রথম ধাপ হল আপনার প্রোগ্রাম ইনপুট-বাউন্ড কিনা তা নির্ধারণ করা। এটি বের করার সবচেয়ে সহজ উপায় হল টেনসরবোর্ডে প্রোফাইলারের ইনপুট-পাইপলাইন বিশ্লেষক ব্যবহার করা, যা ইনপুট পাইপলাইনে ব্যয় করা সময়ের একটি ওভারভিউ প্রদান করে।

image

যদি আপনার ইনপুট-পাইপলাইন ধাপে ধাপে উল্লেখযোগ্যভাবে অবদান রাখে তাহলে আপনি নিম্নলিখিত সম্ভাব্য পদক্ষেপ নিতে পারেন:

  • কিভাবে আপনার ইনপুট পাইপলাইন ডিবাগ করতে হয় তা শিখতে আপনি tf.data নির্দিষ্ট নির্দেশিকা ব্যবহার করতে পারেন।
  • ইনপুট পাইপলাইনটি বাধা কিনা তা পরীক্ষা করার আরেকটি দ্রুত উপায় হল এলোমেলোভাবে জেনারেট করা ইনপুট ডেটা ব্যবহার করা যার কোনো প্রাক-প্রক্রিয়াকরণের প্রয়োজন নেই। এখানে একটি ResNet মডেলের জন্য এই কৌশলটি ব্যবহার করার একটি উদাহরণ । যদি ইনপুট পাইপলাইনটি সর্বোত্তম হয়, তাহলে আপনার বাস্তব ডেটা এবং জেনারেট করা এলোমেলো/সিন্থেটিক ডেটার সাথে অনুরূপ কর্মক্ষমতা অনুভব করা উচিত। সিন্থেটিক ডেটা ক্ষেত্রে একমাত্র ওভারহেড ইনপুট ডেটা কপির কারণে হবে যা আবার প্রিফেচ এবং অপ্টিমাইজ করা যেতে পারে।

উপরন্তু, ইনপুট ডেটা পাইপলাইন অপ্টিমাইজ করার জন্য সর্বোত্তম অনুশীলনগুলি পড়ুন৷

2. একটি GPU-এর কর্মক্ষমতা ডিবাগ করুন

কম জিপিইউ ব্যবহারে অবদান রাখতে পারে এমন কয়েকটি কারণ রয়েছে। ট্রেস ভিউয়ার এবং সম্ভাব্য সমাধানগুলি দেখার সময় নীচে কিছু পরিস্থিতি সাধারণত দেখা যায়৷

1. ধাপগুলির মধ্যে ফাঁক বিশ্লেষণ করুন

একটি সাধারণ পর্যবেক্ষণ যখন আপনার প্রোগ্রামটি সর্বোত্তমভাবে চলছে না তা হল প্রশিক্ষণের ধাপগুলির মধ্যে ফাঁক। নীচের ট্রেস ভিউ-এর ছবিতে, 8 এবং 9 ধাপের মধ্যে একটি বড় ব্যবধান রয়েছে, যার অর্থ এই সময়ে GPU নিষ্ক্রিয় থাকে৷

image

যদি আপনার ট্রেস ভিউয়ার ধাপগুলির মধ্যে বড় ব্যবধান দেখায় তবে এটি একটি ইঙ্গিত হতে পারে যে আপনার প্রোগ্রাম ইনপুট আবদ্ধ। সেই ক্ষেত্রে আপনার ইনপুট পাইপলাইন ডিবাগ করার পূর্ববর্তী বিভাগটি উল্লেখ করা উচিত যদি আপনি ইতিমধ্যে এটি না করে থাকেন।

যাইহোক, এমনকি একটি অপ্টিমাইজ করা ইনপুট পাইপলাইন সহ, আপনি এখনও CPU থ্রেড বিতর্কের কারণে একটি ধাপের শেষ এবং অন্যটির শুরুর মধ্যে ফাঁক থাকতে পারেন। tf.data পাইপলাইন প্রক্রিয়াকরণকে সমান্তরাল করতে ব্যাকগ্রাউন্ড থ্রেড ব্যবহার করে। এই থ্রেডগুলি GPU হোস্ট-সাইড কার্যকলাপে হস্তক্ষেপ করতে পারে যা প্রতিটি ধাপের শুরুতে ঘটে, যেমন ডেটা অনুলিপি করা বা GPU অপারেশনের সময় নির্ধারণ করা।

আপনি যদি হোস্ট সাইডে বড় ফাঁক লক্ষ্য করেন, যা GPU-তে এই অপ্সের সময়সূচী করে, আপনি পরিবেশ পরিবর্তনশীল TF_GPU_THREAD_MODE=gpu_private সেট করতে পারেন। এটি নিশ্চিত করে যে GPU কার্নেলগুলি তাদের নিজস্ব ডেডিকেটেড থ্রেড থেকে চালু হয়েছে এবং tf.data কাজের পিছনে সারিবদ্ধ হবে না।

মেট্রিক গণনা, কেরাস কলব্যাক, বা হোস্টে চলা tf.function এর বাইরে অপ্সের কারণেও ধাপের মধ্যে ফাঁক হতে পারে। টেনসরফ্লো গ্রাফের ভিতরের অপ্সের মতো এই অপ্সের পারফরম্যান্স ততটা ভালো নয়। অতিরিক্তভাবে, এর মধ্যে কিছু অপারেশন CPU-তে চলে এবং GPU থেকে টেনসরগুলিকে সামনে পিছনে কপি করে।

যদি আপনার ইনপুট পাইপলাইন অপ্টিমাইজ করার পরেও আপনি ট্রেস ভিউয়ারের ধাপগুলির মধ্যে ফাঁক লক্ষ্য করেন, তাহলে আপনাকে ধাপগুলির মধ্যে মডেল কোডটি দেখতে হবে এবং কলব্যাক/মেট্রিক্স নিষ্ক্রিয় করলে কর্মক্ষমতা উন্নত হয় কিনা তা পরীক্ষা করা উচিত। এই অপারেশনগুলির কিছু বিবরণ ট্রেস ভিউয়ারে (উভয় ডিভাইস এবং হোস্ট সাইড) রয়েছে৷ এই দৃশ্যে সুপারিশ হল প্রতিটি পদক্ষেপের পরিবর্তে একটি নির্দিষ্ট সংখ্যক পদক্ষেপের পরে এগুলি সম্পাদন করে এই অপ্সগুলির ওভারহেডকে পরিমাপ করা৷ tf.keras API-এ Model.compile পদ্ধতি ব্যবহার করার সময়, steps_per_execution পতাকা সেট করা স্বয়ংক্রিয়ভাবে এটি করে। কাস্টম প্রশিক্ষণ লুপের জন্য, tf.while_loop ব্যবহার করুন।

2. উচ্চতর ডিভাইস ব্যবহার অর্জন

1. ছোট GPU কার্নেল এবং হোস্ট কার্নেল লঞ্চ বিলম্ব

হোস্ট জিপিইউতে চালনার জন্য কার্নেলগুলিকে সারিবদ্ধ করে, কিন্তু জিপিইউতে কার্নেলগুলি কার্যকর করার আগে একটি লেটেন্সি (প্রায় 20-40 μs) জড়িত থাকে। একটি আদর্শ ক্ষেত্রে, হোস্ট GPU-তে পর্যাপ্ত কার্নেল সারিবদ্ধ করে যাতে GPU তার বেশিরভাগ সময় ব্যয় করে, হোস্টের উপর অপেক্ষা না করে আরও কার্নেল সারিবদ্ধ করার জন্য।

টেনসরবোর্ডে প্রোফাইলারের ওভারভিউ পৃষ্ঠা দেখায় যে কার্নেল চালু করার জন্য হোস্টে অপেক্ষা করার কারণে GPU কত সময় নিষ্ক্রিয় ছিল। নীচের ছবিতে, কার্নেল চালু হওয়ার অপেক্ষায় থাকা ধাপের প্রায় 10% সময়ের জন্য GPU নিষ্ক্রিয়।

image

এই একই প্রোগ্রামের ট্রেস ভিউয়ার কার্নেলের মধ্যে ছোট ফাঁক দেখায় যেখানে হোস্ট GPU-তে কার্নেল চালু করতে ব্যস্ত থাকে।

image

GPU-তে অনেকগুলি ছোট অপ্স চালু করে (যেমন একটি স্কেলার অ্যাড, যেমন), হোস্ট GPU এর সাথে তাল মিলিয়ে নাও থাকতে পারে। একই প্রোফাইলের জন্য TensorFlow পরিসংখ্যান টুল 126,224 Mul অপারেশন দেখায় 2.77 সেকেন্ড সময় নেয়। এইভাবে, প্রতিটি কার্নেল প্রায় 21.9 μs, যা খুব ছোট (প্রবর্তনের লেটেন্সির মতো একই সময়ে) এবং সম্ভাব্যভাবে হোস্ট কার্নেল লঞ্চ বিলম্বের কারণ হতে পারে।

image

যদি আপনার ট্রেস ভিউয়ার উপরের চিত্রের মতো GPU-তে অপের মধ্যে অনেক ছোট ফাঁক দেখায়, আপনি করতে পারেন:

  • ছোট টেনসরগুলিকে সংযুক্ত করুন এবং ভেক্টরাইজড অপস ব্যবহার করুন বা প্রতিটি লঞ্চ করা কার্নেলকে আরও কাজ করার জন্য একটি বড় ব্যাচের আকার ব্যবহার করুন, যা GPU কে ​​দীর্ঘ সময়ের জন্য ব্যস্ত রাখবে।
  • নিশ্চিত করুন যে আপনি টেনসরফ্লো গ্রাফ তৈরি করতে tf.function ব্যবহার করছেন, যাতে আপনি একটি বিশুদ্ধ আগ্রহী মোডে অপারেশন চালাচ্ছেন না। আপনি যদি Model.fit ব্যবহার করেন ( tf.GradientTape সহ একটি কাস্টম প্রশিক্ষণ লুপের বিপরীতে), তাহলে tf.keras.Model.compile স্বয়ংক্রিয়ভাবে আপনার জন্য এটি করবে।
  • tf.function(jit_compile=True) বা স্বয়ংক্রিয় ক্লাস্টারিং সহ XLA ব্যবহার করে কার্নেল ফিউজ করুন। আরও বিশদ বিবরণের জন্য, উচ্চ কার্যক্ষমতা পেতে XLA কীভাবে সক্ষম করবেন তা শিখতে নীচের মিশ্র নির্ভুলতা এবং XLA সক্ষম করুন বিভাগে যান৷ এই বৈশিষ্ট্য উচ্চ ডিভাইস ব্যবহার হতে পারে.
2. টেনসরফ্লো অপ প্লেসমেন্ট

প্রোফাইলার ওভারভিউ পৃষ্ঠা আপনাকে হোস্ট বনাম ডিভাইসে স্থাপন করা অপারেশনগুলির শতাংশ দেখায় (আপনি ট্রেস ভিউয়ারটি দেখে নির্দিষ্ট অপারেশনের স্থান নির্ধারণও যাচাই করতে পারেন৷ নীচের চিত্রের মতো, আপনি হোস্টে অপারেশানের শতাংশ চান ডিভাইসের তুলনায় খুব ছোট হতে হবে।

image

আদর্শভাবে, বেশিরভাগ কম্পিউট ইনটেনসিভ অপারেশনগুলি GPU-তে স্থাপন করা উচিত।

আপনার মডেলের অপারেশন এবং টেনসরগুলি কোন ডিভাইসে বরাদ্দ করা হয়েছে তা খুঁজে বের করতে, আপনার প্রোগ্রামের প্রথম বিবৃতি হিসাবে tf.debugging.set_log_device_placement(True) সেট করুন।

মনে রাখবেন যে কিছু ক্ষেত্রে, এমনকি যদি আপনি একটি নির্দিষ্ট ডিভাইসে স্থাপন করার জন্য একটি অপারেটিং নির্দিষ্ট করেন, তবে এটির বাস্তবায়ন এই শর্তকে ওভাররাইড করতে পারে (উদাহরণ: tf.unique )। এমনকি একক GPU প্রশিক্ষণের জন্য, একটি বিতরণ কৌশল নির্দিষ্ট করা, যেমন tf.distribute.OneDeviceStrategy , আপনার ডিভাইসে অপ্সের আরও নির্ধারক স্থান নির্ধারণ করতে পারে।

জিপিইউতে বেশিরভাগ অপ্স স্থাপন করার একটি কারণ হল হোস্ট এবং ডিভাইসের মধ্যে অতিরিক্ত মেমরি কপি প্রতিরোধ করা (হোস্ট এবং ডিভাইসের মধ্যে মডেল ইনপুট/আউটপুট ডেটার জন্য মেমরি কপি প্রত্যাশিত)। অত্যধিক অনুলিপি করার একটি উদাহরণ GPU স্ট্রীম #167 , #168 , এবং #169 -এ নীচের ট্রেস ভিউতে প্রদর্শিত হয়েছে।

image

এই অনুলিপিগুলি কখনও কখনও কর্মক্ষমতা ক্ষতিগ্রস্ত করতে পারে যদি তারা GPU কার্নেলগুলিকে কার্যকর করা থেকে ব্লক করে। ট্রেস ভিউয়ারে মেমরি কপি ক্রিয়াকলাপগুলি এই অনুলিপি করা টেনসরগুলির উত্স সম্পর্কে আরও তথ্য রয়েছে, তবে একটি অপের সাথে একটি মেমকপি সংযুক্ত করা সবসময় সহজ নাও হতে পারে৷ এই ক্ষেত্রে, মেমরি কপি প্রতিটি ধাপে একই স্থানে ঘটছে কিনা তা পরীক্ষা করার জন্য কাছাকাছি অপারেশনগুলি দেখতে সহায়ক।

3. GPU-তে আরও দক্ষ কার্নেল

আপনার প্রোগ্রামের GPU ব্যবহার গ্রহণযোগ্য হয়ে গেলে, পরবর্তী ধাপ হল টেনসর কোর বা ফিউজিং অপস ব্যবহার করে GPU কার্নেলের দক্ষতা বাড়ানোর দিকে নজর দেওয়া।

1. টেনসর কোর ব্যবহার করুন

আধুনিক NVIDIA® GPU-তে বিশেষায়িত টেনসর কোর রয়েছে যা যোগ্য কার্নেলের কর্মক্ষমতা উল্লেখযোগ্যভাবে উন্নত করতে পারে।

কোন জিপিইউ কার্নেলগুলি টেনসর কোর-যোগ্য এবং কোন কার্নেলগুলি টেনসর কোর ব্যবহার করছে তা কল্পনা করতে আপনি টেনসরবোর্ডের GPU কার্নেল পরিসংখ্যান ব্যবহার করতে পারেন৷ আপনার প্রোগ্রামের জেনারেল ম্যাট্রিক্স মাল্টিপ্লাই (জিইএমএম) কার্নেল (ম্যাটমুল অপস) টেনসর কোর ব্যবহার করার জন্য fp16 সক্ষম করা (নীচে মিশ্র স্পষ্টতা বিভাগ সক্রিয় করা দেখুন)। যখন নির্ভুলতা fp16 হয় এবং ইনপুট/আউটপুট টেনসরের মাত্রা 8 বা 16 দ্বারা বিভাজ্য হয় ( int8 এর জন্য) GPU কার্নেলগুলি দক্ষতার সাথে টেনসর কোর ব্যবহার করে।

GPU-এর জন্য কার্নেলগুলিকে কীভাবে দক্ষ করে তোলা যায় সে সম্পর্কে অন্যান্য বিশদ সুপারিশের জন্য, NVIDIA® গভীর শিক্ষার কর্মক্ষমতা নির্দেশিকা পড়ুন।

2. ফিউজ অপারেশন

tf.function(jit_compile=True) ব্যবহার করে ছোট অপ্স ফিউজ করে বড় কার্নেল তৈরি করুন যা উল্লেখযোগ্য কর্মক্ষমতা লাভের দিকে নিয়ে যায়। আরও জানতে, XLA গাইড পড়ুন।

3. মিশ্র নির্ভুলতা এবং XLA সক্ষম করুন

উপরের পদক্ষেপগুলি অনুসরণ করার পরে, মিশ্র নির্ভুলতা এবং XLA সক্ষম করা হল দুটি ঐচ্ছিক পদক্ষেপ যা আপনি কর্মক্ষমতা আরও উন্নত করতে নিতে পারেন। প্রস্তাবিত পদ্ধতি হল তাদের একে একে সক্ষম করা এবং যাচাই করা যে কর্মক্ষমতা সুবিধাগুলি প্রত্যাশা অনুযায়ী।

1. মিশ্র নির্ভুলতা সক্ষম করুন

TensorFlow মিক্সড নির্ভুলতা নির্দেশিকা দেখায় কিভাবে GPU-তে fp16 নির্ভুলতা সক্ষম করতে হয়। টেনসর কোর ব্যবহার করতে NVIDIA® GPU-তে AMP সক্ষম করুন এবং Volta এবং নতুন GPU আর্কিটেকচারে শুধুমাত্র fp32 (float32) নির্ভুলতা ব্যবহারের তুলনায় 3x পর্যন্ত সামগ্রিক গতি উপলব্ধি করুন।

নিশ্চিত করুন যে ম্যাট্রিক্স/টেনসরের মাত্রাগুলি টেনসর কোর ব্যবহার করে এমন কার্নেল কল করার প্রয়োজনীয়তাগুলি পূরণ করে৷ যখন নির্ভুলতা fp16 হয় এবং ইনপুট/আউটপুট মাত্রা 8 বা 16 দ্বারা বিভাজ্য হয় (int8-এর জন্য) GPU কার্নেলগুলি দক্ষতার সাথে টেনসর কোর ব্যবহার করে।

মনে রাখবেন যে cuDNN v7.6.3 এবং পরবর্তীতে, কনভোলিউশন ডাইমেনশনগুলি স্বয়ংক্রিয়ভাবে প্যাড করা হবে যেখানে প্রয়োজন টেনসর কোরগুলিকে লিভারেজ করার জন্য।

fp16 নির্ভুলতার পারফরম্যান্স সুবিধাগুলি সর্বাধিক করতে নীচের সেরা অনুশীলনগুলি অনুসরণ করুন৷

1. সর্বোত্তম fp16 কার্নেল ব্যবহার করুন

fp16 সক্ষম হলে, আপনার প্রোগ্রামের ম্যাট্রিক্স গুণন (GEMM) কার্নেলগুলিকে সংশ্লিষ্ট fp16 সংস্করণ ব্যবহার করা উচিত যা টেনসর কোর ব্যবহার করে। যাইহোক, কিছু ক্ষেত্রে, এটি ঘটে না এবং আপনি fp16 সক্রিয় করার থেকে প্রত্যাশিত গতির অভিজ্ঞতা পান না, কারণ আপনার প্রোগ্রামটি এর পরিবর্তে অদক্ষ বাস্তবায়নে ফিরে আসে।

image

GPU কার্নেল পরিসংখ্যান পৃষ্ঠা দেখায় কোন অপ্সগুলি টেনসর কোর যোগ্য এবং কোন কার্নেলগুলি আসলে দক্ষ টেনসর কোর ব্যবহার করছে৷ ডিপ লার্নিং পারফরম্যান্সের উপর NVIDIA® গাইডে টেনসর কোরকে কীভাবে ব্যবহার করা যায় সে সম্পর্কে অতিরিক্ত পরামর্শ রয়েছে। অতিরিক্তভাবে, fp16 ব্যবহারের সুবিধাগুলি কার্নেলগুলিতেও দেখাবে যেগুলি পূর্বে মেমরি বাউন্ড ছিল, কারণ এখন অপ্সগুলি অর্ধেক সময় নেবে।

2. ডাইনামিক বনাম স্ট্যাটিক লস স্কেলিং

কম নির্ভুলতার কারণে আন্ডারফ্লো রোধ করতে fp16 ব্যবহার করার সময় লস স্কেলিং প্রয়োজন। দুই ধরনের ক্ষতির স্কেলিং আছে, গতিশীল এবং স্থির, উভয়ই মিশ্র যথার্থ নির্দেশিকাতে আরও বিশদভাবে ব্যাখ্যা করা হয়েছে। কেরাস অপ্টিমাইজারের মধ্যে স্বয়ংক্রিয়ভাবে ক্ষতি স্কেলিং সক্ষম করতে আপনি mixed_float16 নীতি ব্যবহার করতে পারেন।

কর্মক্ষমতা অপ্টিমাইজ করার চেষ্টা করার সময়, এটি মনে রাখা গুরুত্বপূর্ণ যে ডায়নামিক লস স্কেলিং হোস্টে চলা অতিরিক্ত শর্তসাপেক্ষ অপারেশনগুলি প্রবর্তন করতে পারে এবং ট্রেস ভিউয়ারের ধাপগুলির মধ্যে দৃশ্যমান গ্যাপগুলির দিকে নিয়ে যেতে পারে৷ অন্যদিকে, স্ট্যাটিক লস স্কেলিং-এ এই ধরনের ওভারহেড থাকে না এবং ক্যাচের সাথে পারফরম্যান্সের ক্ষেত্রে এটি একটি ভাল বিকল্প হতে পারে যা আপনাকে সঠিক স্ট্যাটিক-লস স্কেল মান নির্দিষ্ট করতে হবে।

2. tf.function(jit_compile=True) বা স্বয়ংক্রিয় ক্লাস্টারিং সহ XLA সক্ষম করুন

একটি একক GPU এর সাথে সেরা পারফরম্যান্স পাওয়ার চূড়ান্ত পদক্ষেপ হিসাবে, আপনি XLA সক্ষম করার সাথে পরীক্ষা করতে পারেন, যা অপ্সকে ফিউজ করবে এবং ডিভাইসের আরও ভাল ব্যবহার এবং কম মেমরির পদচিহ্নের দিকে নিয়ে যাবে। tf.function(jit_compile=True) বা স্বয়ংক্রিয়-ক্লাস্টারিংয়ের মাধ্যমে কীভাবে আপনার প্রোগ্রামে XLA সক্ষম করবেন তার বিশদ বিবরণের জন্য, XLA নির্দেশিকা পড়ুন।

আপনি গ্লোবাল JIT লেভেল -1 (বন্ধ), 1 বা 2 এ সেট করতে পারেন। একটি উচ্চ স্তর আরও আক্রমনাত্মক এবং সমান্তরালতা হ্রাস করতে পারে এবং আরও মেমরি ব্যবহার করতে পারে। আপনার মেমরি সীমাবদ্ধতা থাকলে মানটি 1 এ সেট করুন। মনে রাখবেন যে পরিবর্তনশীল ইনপুট টেনসর আকারের মডেলগুলির জন্য XLA ভাল কাজ করে না কারণ XLA কম্পাইলারকে যখনই এটি নতুন আকারের সম্মুখীন হয় তখন কার্নেলগুলি কম্পাইল করতে হবে৷

2. মাল্টি-GPU একক হোস্টে কর্মক্ষমতা অপ্টিমাইজ করুন

tf.distribute.MirroredStrategy API একক হোস্টে এক GPU থেকে একাধিক GPU-তে মডেল প্রশিক্ষণ স্কেল করতে ব্যবহার করা যেতে পারে। (TensorFlow-এর সাহায্যে কীভাবে বিতরণ করা হয় সে সম্পর্কে আরও জানতে, TensorFlow-এর সাহায্যে বিতরণ করা প্রশিক্ষণ পড়ুন, একটি GPU ব্যবহার করুন , এবং TPUs গাইড ব্যবহার করুন এবং কেরাস টিউটোরিয়াল সহ বিতরণ করা প্রশিক্ষণ দেখুন ।)

যদিও এক GPU থেকে একাধিক GPU-তে রূপান্তর আদর্শভাবে বাক্সের বাইরে স্কেলযোগ্য হওয়া উচিত, আপনি কখনও কখনও কর্মক্ষমতা সমস্যার সম্মুখীন হতে পারেন।

একই হোস্টে একটি একক GPU সহ একাধিক GPU-তে প্রশিক্ষণ নেওয়ার সময়, আদর্শভাবে আপনি শুধুমাত্র গ্রেডিয়েন্ট কমিউনিকেশনের অতিরিক্ত ওভারহেড এবং হোস্ট থ্রেড ব্যবহার বৃদ্ধির সাথে পারফরম্যান্স স্কেলিংয়ের অভিজ্ঞতা লাভ করবেন। এই ওভারহেডের কারণে, উদাহরণস্বরূপ, আপনি যদি 1 থেকে 2 জিপিইউ থেকে সরে যান তবে আপনার কাছে সঠিক 2x গতি থাকবে না।

নীচের ট্রেস ভিউ একাধিক GPU-তে প্রশিক্ষণের সময় অতিরিক্ত যোগাযোগের ওভারহেডের একটি উদাহরণ দেখায়। গ্রেডিয়েন্টগুলিকে একত্রিত করার জন্য কিছু ওভারহেড রয়েছে, তাদের প্রতিলিপি জুড়ে যোগাযোগ করতে এবং ওজন আপডেট করার আগে সেগুলিকে বিভক্ত করে।

image

মাল্টি-জিপিইউ পরিস্থিতিতে কর্মক্ষমতা অপ্টিমাইজ করার সময় নিম্নলিখিত চেকলিস্ট আপনাকে আরও ভাল পারফরম্যান্স অর্জনে সহায়তা করবে:

  1. ব্যাচের আকার সর্বাধিক করার চেষ্টা করুন, যা উচ্চতর ডিভাইস ব্যবহারে নেতৃত্ব দেবে এবং একাধিক জিপিইউ জুড়ে যোগাযোগের খরচ পরিমাপ করবে। মেমরি প্রোফাইলার ব্যবহার করে আপনার প্রোগ্রামটি মেমরির ব্যবহারের শীর্ষে কতটা কাছাকাছি তা বুঝতে সাহায্য করে। মনে রাখবেন যে উচ্চতর ব্যাচের আকার অভিসারকে প্রভাবিত করতে পারে, এটি সাধারণত কর্মক্ষমতা সুবিধার দ্বারা বেশি হয়।
  2. একক GPU থেকে একাধিক GPU-তে যাওয়ার সময়, একই হোস্টকে এখন অনেক বেশি ইনপুট ডেটা প্রক্রিয়া করতে হবে। সুতরাং, (1) এর পরে, ইনপুট পাইপলাইনের কার্যকারিতা পুনরায় পরীক্ষা করার এবং এটি কোনও বাধা নয় তা নিশ্চিত করার পরামর্শ দেওয়া হয়।
  3. যেকোনো অপ্রয়োজনীয় AllReduce কলের জন্য আপনার প্রোগ্রামের ট্রেস ভিউতে GPU টাইমলাইন চেক করুন, কারণ এর ফলে সমস্ত ডিভাইস জুড়ে সিঙ্ক্রোনাইজেশন হয়। উপরে দেখানো ট্রেস ভিউতে, AllReduce NCCL কার্নেলের মাধ্যমে করা হয়, এবং প্রতিটি ধাপে গ্রেডিয়েন্টের জন্য প্রতিটি GPU-তে শুধুমাত্র একটি NCCL কল আছে।
  4. অপ্রয়োজনীয় D2H, H2D এবং D2D কপি ক্রিয়াকলাপগুলির জন্য পরীক্ষা করুন যা কম করা যেতে পারে।
  5. প্রতিটি প্রতিরূপ একই কাজ করছে তা নিশ্চিত করতে ধাপের সময় পরীক্ষা করুন। উদাহরণস্বরূপ, এটি ঘটতে পারে যে একটি জিপিইউ (সাধারণত, GPU0 ) ওভারসাবস্ক্রাইব করা হয়েছে কারণ হোস্ট ভুলবশত এটিতে আরও কাজ করে ফেলে।
  6. সবশেষে, আপনার ট্রেস ভিউতে সমস্ত জিপিইউ জুড়ে প্রশিক্ষণের ধাপটি পর্যায়ক্রমে নির্বাহ করা যে কোনও অপারেশনের জন্য পরীক্ষা করুন। এটি সাধারণত ঘটে যখন আপনার প্রোগ্রামে এক GPU থেকে অন্য GPU-তে নিয়ন্ত্রণ নির্ভরতা অন্তর্ভুক্ত থাকে। অতীতে, এই পরিস্থিতিতে পারফরম্যান্স ডিবাগ করা কেস-বাই-কেস ভিত্তিতে সমাধান করা হয়েছে। আপনি যদি আপনার প্রোগ্রামে এই আচরণটি পর্যবেক্ষণ করেন তবে আপনার ট্রেস ভিউয়ের চিত্রগুলির সাথে একটি গিটহাব সমস্যা ফাইল করুন

1. গ্রেডিয়েন্ট AllReduce অপ্টিমাইজ করুন

একটি সিঙ্ক্রোনাস কৌশলের সাথে প্রশিক্ষণের সময়, প্রতিটি ডিভাইস ইনপুট ডেটার একটি অংশ গ্রহণ করে।

মডেলের মধ্য দিয়ে এগিয়ে এবং পিছনের পাসগুলি গণনা করার পরে, প্রতিটি ডিভাইসে গণনা করা গ্রেডিয়েন্টগুলিকে একত্রিত এবং হ্রাস করতে হবে। এই গ্রেডিয়েন্ট AllReduce প্রতিটি ডিভাইসে গ্রেডিয়েন্ট গণনার পরে এবং অপ্টিমাইজার মডেলের ওজন আপডেট করার আগে ঘটে।

প্রতিটি GPU প্রথমে মডেল স্তর জুড়ে গ্রেডিয়েন্টগুলিকে একত্রিত করে, tf.distribute.CrossDeviceOps ( tf.distribute.NcclAllReduce হল ডিফল্ট) ব্যবহার করে GPU গুলি জুড়ে তাদের যোগাযোগ করে, এবং তারপর স্তর প্রতি হ্রাস করার পরে গ্রেডিয়েন্টগুলি ফেরত দেয়৷

অপ্টিমাইজার আপনার মডেলের ওজন আপডেট করতে এই হ্রাস করা গ্রেডিয়েন্ট ব্যবহার করবে। আদর্শভাবে, কোনো ওভারহেড প্রতিরোধ করতে এই প্রক্রিয়াটি সমস্ত GPU-তে একই সময়ে হওয়া উচিত।

AllReduce করার সময় প্রায় একই হওয়া উচিত:

(number of parameters * 4bytes)/ (communication bandwidth)

একটি বিতরণ করা প্রশিক্ষণ কাজ চালানোর সময় আপনার কর্মক্ষমতা প্রত্যাশিত কিনা বা আপনাকে আরও কর্মক্ষমতা ডিবাগিং করতে হবে কিনা তা বোঝার জন্য এই গণনাটি একটি দ্রুত পরীক্ষা হিসাবে কার্যকর। আপনি Model.summary থেকে আপনার মডেলের প্যারামিটারের সংখ্যা পেতে পারেন।

মনে রাখবেন যে প্রতিটি মডেলের প্যারামিটার 4 বাইট আকারের হয় যেহেতু টেনসরফ্লো গ্রেডিয়েন্টের সাথে যোগাযোগ করতে fp32 (float32) ব্যবহার করে। এমনকি যখন আপনি fp16 সক্ষম করেন, NCCL AllReduce fp32 প্যারামিটার ব্যবহার করে।

স্কেলিংয়ের সুবিধা পেতে, এই ওভারহেডগুলির তুলনায় ধাপ-সময় অনেক বেশি হওয়া প্রয়োজন। এটি অর্জনের একটি উপায় হল একটি উচ্চ ব্যাচের আকার ব্যবহার করা কারণ ব্যাচের আকার ধাপের সময়কে প্রভাবিত করে, কিন্তু যোগাযোগের ওভারহেডকে প্রভাবিত করে না।

2. GPU হোস্ট থ্রেড বিতর্ক

একাধিক GPU চালানোর সময়, CPU-এর কাজ হল সমস্ত ডিভাইস জুড়ে GPU কার্নেলগুলিকে দক্ষতার সাথে চালু করে সমস্ত ডিভাইসকে ব্যস্ত রাখা।

যাইহোক, যখন সিপিইউ একটি জিপিইউতে অনেকগুলি স্বাধীন ক্রিয়াকলাপ নির্ধারণ করতে পারে, তখন সিপিইউ একটি জিপিইউকে ব্যস্ত রাখার জন্য তার অনেক হোস্ট থ্রেড ব্যবহার করার সিদ্ধান্ত নিতে পারে এবং তারপরে একটি অ-নির্ধারিত ক্রমে অন্য জিপিইউতে কার্নেল চালু করতে পারে। . এটি একটি তির্যক বা নেতিবাচক স্কেলিং হতে পারে, যা কার্যকারিতাকে নেতিবাচকভাবে প্রভাবিত করতে পারে।

নিচের ট্রেস ভিউয়ারটি ওভারহেড দেখায় যখন CPU স্তব্ধ করে দেয় GPU কার্নেল অকার্যকরভাবে চালু হয়, কারণ GPU1 নিষ্ক্রিয় থাকে এবং GPU2 শুরু হওয়ার পরে অপারেশন চালানো শুরু করে।

image

হোস্টের জন্য ট্রেস ভিউ দেখায় যে হোস্ট GPU1 এ চালু করার আগে GPU2 তে কার্নেল চালু করছে (উল্লেখ্য যে নীচের tf_Compute* opsগুলি CPU থ্রেডগুলির নির্দেশক নয়)।

image

আপনি যদি আপনার প্রোগ্রামের ট্রেস ভিউতে জিপিইউ কার্নেলের এই ধরনের বিস্ময়কর অবস্থা অনুভব করেন, তাহলে প্রস্তাবিত পদক্ষেপ হল:

  • TensorFlow এনভায়রনমেন্ট ভেরিয়েবল TF_GPU_THREAD_MODE কে gpu_private এ সেট করুন। এই এনভায়রনমেন্ট ভেরিয়েবল হোস্টকে একটি GPU প্রাইভেট এর জন্য থ্রেড রাখতে বলবে।
  • ডিফল্টরূপে, TF_GPU_THREAD_MODE=gpu_private থ্রেডের সংখ্যা 2 এ সেট করে, যা বেশিরভাগ ক্ষেত্রেই যথেষ্ট। যাইহোক, TensorFlow এনভায়রনমেন্ট ভেরিয়েবল TF_GPU_THREAD_COUNT কে কাঙ্খিত থ্রেডে সেট করে সেই সংখ্যাটি পরিবর্তন করা যেতে পারে।