সমান্তরাল প্রক্রিয়াগুলিতে স্টিডিন ছড়িয়ে দেওয়া


13

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

find . -type f | split -n r/24 -u --filter="myjob"
find . -type f | parallel --pipe -u -l 1 myjob

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

এর মতো কি এমন কিছু রয়েছে যা প্রসেস এবং ফিড লাইনগুলির যে কোনও প্রক্রিয়াতে স্টলিনগুলিকে অবরোধযুক্ত করে রাখতে পুনরায় ব্যবহার করবে?


সেই splitআদেশটি কোথা থেকে এসেছে? নামটি স্ট্যান্ডার্ড পাঠ্য প্রক্রিয়াকরণ ইউটিলিটির সাথে বিরোধ করে ।
গিলস 'অশুভ হওয়া বন্ধ করুন'

@ গিলস, এটি জিএনইউ এক: "বিভক্ত (জিএনইউ কোর্টিলস) ৮.১৩" । এটিকে xargs এর একটি অদ্ভুত বিকল্প হিসাবে ব্যবহার করা সম্ভবত উদ্দিষ্ট ব্যবহার নয় তবে এটি আমি যা চাই তা সবচেয়ে নিকটে।
বিসিওয়েটস

2
আমি সে সম্পর্কে ভাবছিলাম, এবং একটি মৌলিক সমস্যাটি জেনে গেছে যে একটি উদাহরণ myjobআরও ইনপুট গ্রহণের জন্য প্রস্তুত। কোনও প্রোগ্রাম আরও ইনপুট প্রক্রিয়াজাতকরণের জন্য প্রস্তুত তা জানার কোনও উপায় নেই, আপনি কেবলমাত্র জানতে পারেন যে কোথাও কিছু বাফার (একটি পাইপ বাফার, একটি স্টিডিও বাফার) আরও ইনপুট গ্রহণের জন্য প্রস্তুত। আপনার প্রোগ্রামটি প্রস্তুত হয়ে গেলে কোনও প্রকারের অনুরোধ (যেমন একটি প্রম্পট প্রদর্শন করুন) প্রেরণের ব্যবস্থা করতে পারেন?
গিলস 'অশুভ হওয়া বন্ধ করুন'

ধরে নিই যে প্রোগ্রামটি স্টিডিনে বুফারিং ব্যবহার করছে না, একটি FUSE ফাইল সিস্টেম যা readকলগুলিতে প্রতিক্রিয়া দেখায় তা কৌশলটি করবে। এটি মোটামুটি বড় প্রোগ্রামিং প্রচেষ্টা।
গিলস 'অশুভ হওয়া বন্ধ করুন'

আপনি কেন ব্যবহার -l 1করছেন parallel? আইআইআরসি, যা প্রতি চাকরির জন্য এক লাইন ইনপুট প্রক্রিয়া করার সমান্তরাল বলে (যেমন মাইজবের কাঁটাচামচের জন্য একটি ফাইলের নাম, যাতে প্রচুর পরিমাণে ওভারহেড)।
কাশ

উত্তর:


1

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

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

তবে এটি আপনার ব্যবহারের ক্ষেত্রে নির্ভর করে।


1

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


0

আমি তাই মনে করি না. আমার প্রিয় ম্যাগাজিনে একবার বাশ প্রোগ্রামিংয়ের একটি নিবন্ধ ছিল যা আপনি যা চান তা করে। আমি বিশ্বাস করতে ইচ্ছুক যে যদি এখানে এমন কিছু করার ব্যবস্থা ছিল যে তারা তাদের উল্লেখ করত। সুতরাং আপনি এই লাইনের পাশাপাশি কিছু চান:

set -m # enable job control
max_processes=8
concurrent_processes=0

child_has_ended() { concurrent_processes=$((concurrent_processes - 1)) }

trap child_has_ended SIGCHLD # that's magic calling our bash function when a child processes ends

for i in $(find . -type f)
do
  # don't do anything while there are max_processes running
  while [ ${concurrent_processes} -ge ${max_processes}]; do sleep 0.5; done 
  # increase the counter
  concurrent_processes=$((concurrent_processes + 1))
  # start a child process to actually deal with one file
  /path/to/script/to/handle/one/file $i &
done

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

অস্বীকারকারী আমি আমার স্ক্রিনটি আমার মাথার উপর থেকে লিখেছি। এতে কিছু সিনট্যাক্স সমস্যা থাকতে পারে।


1
এটি প্রয়োজনীয়তাগুলি মেটাচ্ছে বলে মনে হচ্ছে না: আপনি প্রতিটি আইটেমের জন্য প্রোগ্রামের একটি আলাদা উদাহরণ শুরু করছেন।
গিলস 'অশুভ হওয়া বন্ধ করুন'

find . -type f | while read iবরং এটি ব্যবহার করার চেয়ে সাধারণত ব্যবহার করা ভাল for i in $(find . -type f)

0

জিএনইউ সমান্তরাল জন্য আপনি - ব্লক ব্যবহার করে ব্লকের আকার নির্ধারণ করতে পারেন। এটি অবশ্য আপনার চলমান প্রতিটি প্রক্রিয়ার জন্য মেমরিতে 1 টি ব্লক রাখার জন্য পর্যাপ্ত মেমরির প্রয়োজন।

আমি বুঝতে পারি এটি আপনি যা সন্ধান করছেন তা অবিকল নয়, তবে এটি আপাতত একটি গ্রহণযোগ্য কাজ হতে পারে।

যদি আপনার কাজগুলিতে গড় সময় একই সময় নেয়, তবে আপনি এমবাফার ব্যবহার করতে সক্ষম হতে পারেন:

find . -type f | split -n r/24 -u --filter="mbuffer -m 2G | myjob"

0

এটা চেষ্টা কর:

mkfifo প্রতিটি প্রক্রিয়া জন্য।

তারপরে tail -f | myjobপ্রতিটি ফিফোর উপর ঝুলুন।

উদাহরণস্বরূপ কর্মীদের স্থাপন (মাইজব প্রক্রিয়াগুলি)

mkdir /tmp/jobs
for X in 1 2 3 4
do
   mkfifo pipe$X
   tail -f pipe$X | myjob &
   jobs -l| awk '/pipe'$X'/ {print $2, "'pipe$X'"}' >> pipe-job-mapping
done

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

ইনপুট, ব্যবহারের অপেক্ষায় যখন কাজ বন্ধ হয়ে যায় তা ধরে নেওয়া

jobs -sl একটি থামানো কাজের পিড খুঁজে বের করতে এবং এটিকে কাজ নির্ধারণ করার জন্য

grep "^$STOPPED_PID" pipe-to-job-mapping | while read PID PIPE
do
   cat workset > $PIPE
done

আমি এটি দিয়ে পরীক্ষা করেছি

garfield:~$ cd /tmp
garfield:/tmp$ mkfifo f1
garfield:/tmp$ mkfifo f2
garfield:/tmp$ tail -f f1 | sed 's/^/1 /' &
[1] 21056
garfield:/tmp$ tail -f f2 | sed 's/^/2 /' &
[2] 21058
garfield:/tmp$ echo hello > f1
1 hello
garfield:/tmp$ echo what > f2
2 what
garfield:/tmp$ echo yes > f1
1 yes

এই আমি অবশ্যই স্বীকার করা আবশ্যক ymmv।


0

এটি সমাধানের জন্য আসলে যা প্রয়োজন তা হ'ল কিছু প্রকারের একটি সারি প্রক্রিয়া।

কাজগুলি কি কিউ থেকে তাদের ইনপুট পড়ার যেমন একটি এসওয়াইএসভি বার্তা সারি, এবং তারপরে প্রোগ্রামগুলি সমান্তরালভাবে চালিত করে কি মানগুলিকে কিউয়ের উপরে চাপানো সম্ভব?

আর একটি সম্ভাবনা হ'ল এইভাবে সারির জন্য ডিরেক্টরি ব্যবহার করা:

  1. ফাইন্ড আউটপুট একটি ডিরেক্টরিতে প্রক্রিয়া করার জন্য প্রতিটি ফাইলের একটি সিলিমিংক তৈরি করে, pending
  2. প্রতিটি কাজের প্রক্রিয়া mvএটি pendingনামের একটি ভাইবাল ডিরেক্টরিতে ডিরেক্টরিতে দেখায় এমন প্রথম ফাইলের একটি করে inprogress
  3. যদি কাজটি সফলভাবে ফাইলটি সরায়, এটি প্রক্রিয়া সম্পাদন করে; অন্যথায়, এটি থেকে অন্য ফাইলের নামটি সন্ধান এবং সরানোতে ফিরে যায়pending

0

@ অ্যাশ এর উত্তরটি ব্যাখ্যা করে, আপনি কাজটি বিতরণের জন্য একটি এসওয়াইএসভি বার্তা সারি ব্যবহার করতে পারেন। আপনি যদি সি তে নিজের প্রোগ্রাম লিখতে না চান তবে এমন একটি ইউটিলিটি রয়েছে যা ipcmdসাহায্য করতে পারে। এখানে কি আমি একত্র করা আউটপুট পাস করার find $DIRECTORY -type fজন্য $PARALLELপ্রসেস সংখ্যা:

set -o errexit
set -o nounset

export IPCMD_MSQID=$(ipcmd msgget)

DIRECTORY=$1
PARALLEL=$2

# clean up message queue on exit
trap 'ipcrm -q $IPCMD_MSQID' EXIT

for i in $(seq $PARALLEL); do
   {
      while true
      do
          message=$(ipcmd msgrcv) || exit
          [ -f $message ] || break
          sleep $((RANDOM/3000))
      done
   } &
done

find "$DIRECTORY" -type f | xargs ipcmd msgsnd

for i in $(seq $PARALLEL); do
   ipcmd msgsnd "/dev/null/bar"
done
wait

এখানে একটি পরীক্ষা চালানো হয়েছে:

$ for i in $(seq 20 10 100) ; do time parallel.sh /usr/lib/ $i ; done
parallel.sh /usr/lib/ $i  0.30s user 0.67s system 0% cpu 1:57.23 total
parallel.sh /usr/lib/ $i  0.28s user 0.69s system 1% cpu 1:09.58 total
parallel.sh /usr/lib/ $i  0.19s user 0.80s system 1% cpu 1:05.29 total
parallel.sh /usr/lib/ $i  0.29s user 0.73s system 2% cpu 44.417 total
parallel.sh /usr/lib/ $i  0.25s user 0.80s system 2% cpu 37.353 total
parallel.sh /usr/lib/ $i  0.21s user 0.85s system 3% cpu 32.354 total
parallel.sh /usr/lib/ $i  0.30s user 0.82s system 3% cpu 28.542 total
parallel.sh /usr/lib/ $i  0.27s user 0.88s system 3% cpu 30.219 total
parallel.sh /usr/lib/ $i  0.34s user 0.84s system 4% cpu 26.535 total

0

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


0

জিএনইউ সমান্তরাল গত 7 বছরে পরিবর্তিত হয়েছে। সুতরাং আজ এটি করতে পারে:

এই উদাহরণটি দেখায় যে প্রসেস 4 এবং 5 এর চেয়ে 11 এবং 10 প্রসেসের জন্য আরও ব্লক দেওয়া হয় কারণ 4 এবং 5 ধীরে ধীরে পড়ে:

seq 1000000 |
  parallel -j8 --tag --roundrobin --pipe --block 1k 'pv -qL {}0000 | wc' ::: 11 4 5 6 9 8 7 10
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.