সমান্তরাল শেল loops


11

আমি অনেক ফাইল প্রক্রিয়া করতে চাই এবং আমি এখানে কোরে একটি গুচ্ছ আছে যা আমি সমান্তরাল করতে চাই:

for i in *.myfiles; do do_something $i `derived_params $i` other_params; done

আমি একটি Makefile সমাধান সম্পর্কে জানি কিন্তু আমার কমান্ডগুলি শেল গ্লোববিং তালিকা থেকে আর্গুমেন্টগুলির প্রয়োজন। আমি কি পাওয়া যায়:

> function pwait() {
>     while [ $(jobs -p | wc -l) -ge $1 ]; do
>         sleep 1
>     done
> }
>

এটি ব্যবহার করার জন্য, সকলকে কাজ করতে হবে এবং চাকরি এবং একটি পওয়াট কল পরে, প্যারামিটার সমান্তরাল প্রসেসের সংখ্যা দেয়:

> for i in *; do
>     do_something $i &
>     pwait 10
> done

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

আমি বিশ্বাস করতে পারছি না যে এই কাজটি এখনো সম্পন্ন হয়নি, যেহেতু zsh মেইলিং লিস্টের আলোচনা এখন এত পুরানো। তাই আপনি কোন ভাল জানেন?


এই প্রশ্নের অনুরূপ: superuser.com/questions/153630/... দেখুন যে কৌশল আপনার জন্য কাজ করে।
JRobert

আপনি ত্রুটির বার্তা পোস্ট করলে এটি সহায়ক হবে।
ডেনিস উইলিয়ামসন

@ জেরববার্ট হ্যাঁ আমি এটা জানতাম কিন্তু আসলেই এটি সাহায্য করে না কারণ মেকফিল পদ্ধতির কাজ আমি করব না! @ ডেনিস: ঠিক আছে, প্রথমে আমি নির্দিষ্ট সংখ্যক প্রসেসের চেয়ে আমাকে আরো দেখানোর পাশে একটি শীর্ষে চালাও। দ্বিতীয়ত এটি সঠিকভাবে প্রম্পটে ফিরে না। তৃতীয় যে আমি বলেছিলাম যে এটি কাজকে পূর্বাবস্থায় ফিরিয়ে দেয়, তা সঠিক ছিল না: echo "DONE"সক্রিয় কাজগুলি শেষ না হওয়ার আগে আমি কেবল লুপটি কার্যকর করার পরে একটি নির্দেশক স্থাপন করেছি । => এটি আমাকে ভুগছে কাজ মনে করে।
গণিত

উত্তর:


14

একটি Makefile হয় আপনার সমস্যা একটি ভাল সমাধান। আপনি একটি শেল এই সমান্তরাল execution প্রোগ্রাম করতে পারে, কিন্তু আপনি লক্ষ্য করেছি, এটা কঠিন। মেকের সমান্তরাল বাস্তবায়ন কেবল কাজ শুরু করার এবং তাদের অবসান সনাক্ত করার জন্যই নয়, লোড ভারসাম্যকেও হ্যান্ডেল করবে, যা চতুর।

Globbing জন্য প্রয়োজন একটি বাধা না: এটি সমর্থন করে যে বাস্তবায়ন করা হয়। জিএনইউ মেক, যা ওয়াইল্ডকার্ড সম্প্রসারণের মতো $(wildcard *.c)এবং শেল অ্যাক্সেসের মতো রয়েছে $(shell mycommand)(আরও তথ্যের জন্য GNU ম্যানুয়াল তৈরির ফাংশনগুলি দেখুন)। এটি makeলিনাক্সে ডিফল্ট এবং অন্যান্য বেশিরভাগ সিস্টেমে উপলব্ধ। এখানে একটি মেকফিল কঙ্কাল রয়েছে যা আপনি আপনার প্রয়োজনগুলির সাথে মানিয়ে নিতে সক্ষম হতে পারেন:

উত্স = $ (ওয়াইল্ডকার্ড *। এসআরসি)

সব: $ (উত্স:। এসআরসি = .tgt)

% .tgt: $। এসআরসি
    do_sthingthing $ <$$ (derived_params $ <)> $ @

make -j4সমান্তরালে চারটি কাজ চালানো বা make -j -l3লোড গড় প্রায় 3 রাখা চালানোর মতো কিছু চালান ।


8

আমি আপনার প্রাপ্ত আর্গুমেন্ট মত কি নিশ্চিত নই। কিন্তু জিএনইউ সমান্তরাল http: // www.gnu.org/software/parallel/ আপনি সিপিইউ কোর প্রতি এক কাজ চালানোর জন্য এটি করতে পারেন:

find . | parallel -j+0 'a={}; name=${a##*/}; upper=$(echo "$name" | tr "[:lower:]" "[:upper:]");
   echo "$name - $upper"'

আপনি যা অর্জন করতে চান তা কেবলমাত্র পরিবর্তন করা হচ্ছে। এক্সটেনশানটি {।} সহজ হতে পারে:

parallel -j+0 lame {} -o {.}.mp3 ::: *.wav

Http://www.youtube.com/watch?v=OpaiGYxkSuQ এ জিএনইউ সমান্তরাল এন্ট্রো ভিডিওটি দেখুন


6

আপনার জন্য শেল এর waitকমান্ড কাজ ব্যবহার করবেন না ?

for i in *
do
    do_something $i &
done
wait

আপনার লুপ একটি কাজ সঞ্চালিত তারপর এটি জন্য অপেক্ষা করে, তারপর পরবর্তী কাজ করে। উপরেরটি যদি আপনার জন্য কাজ না করে তবে আপনি pwaitপরে স্থানান্তরিত হলে আপনার আরও ভাল কাজ করতে পারে done


1 কোটি ফাইলের সাথে 1 মিলিয়ন প্রসেস চলবে না, নাকি আমি ভুল?
গণিত

1
@brubelsabs: ভাল, এটি একটি মিলিয়ন প্রসেস করতে চেষ্টা করবে । আপনার প্রশ্নে আপনি কতগুলি ফাইল প্রক্রিয়া করতে চান তা আপনার কাছে বলা হয়নি। আমি ভাবতে চাই যে আপনি নেস্টেড forলুপগুলি সীমাবদ্ধ করার জন্য এটি ব্যবহার করতে হবে : for file in *; do for i in {1..10}; do do_something "$i" & done; wait; done(অনির্বাচিত) এটি একবারে দশটি করা উচিত এবং পরবর্তী দশটি শুরু করার আগে প্রতিটি গোষ্ঠীর দশটি সম্পন্ন হওয়া পর্যন্ত অপেক্ষা করা উচিত। আপনার লুপ একটি সময়ে &moot করা এক। JRobert অন্যান্য বিকল্পের জন্য লিঙ্ক যে প্রশ্ন দেখুন । আপনার অনুরূপ অন্যান্য প্রশ্নগুলির জন্য স্ট্যাক ওভারফ্লো অনুসন্ধান করুন (এবং যে এক)।
ডেনিস উইলিয়ামসন

ওপি যদি এক মিলিয়ন ফাইলের প্রত্যাশা করে তাহলে তার সাথে একটি সমস্যা হবে for i in *। তিনি একটি পাইপ বা কিছু সঙ্গে লুপ আর্গুমেন্ট পাস করতে হবে। তারপরে একটি অভ্যন্তরীণ লুপের পরিবর্তে আপনি একটি ক্রমবর্ধমান পাল্টা চালাতে পারেন এবং "micro-"wait"-s"প্রতি "$ ((i% 32))" -eq '0'

@ ডেনিস উইলিয়ামসন: waitএকটি অভ্যন্তরীণ পাল্টা লুপের সাথে সংমিশ্রণ আমার জন্য ভাল কাজ করেছে। ধন্যবাদ!
জোয়েল পুর্রা

3

কেন এখনো কেউ জার্গ উল্লেখ করেনি?

আপনি ঠিক তিনটি আর্গুমেন্ট আছে অনুমান,

for i in *.myfiles; do echo -n $i `derived_params $i` other_params; done | xargs -n 3 -P $PROCS do_something

অন্যথায় একটি ডিলিমিটার ব্যবহার করুন (নাল তার জন্য সহজ):

for i in *.myfiles; do echo -n $i `derived_params $i` other_params; echo -ne "\0"; done | xargs -0 -n 1 -P $PROCS do_something

সম্পাদনা করুন: উপরের জন্য, প্রতিটি প্যারামিটারটি একটি নিল চরিত্র দ্বারা আলাদা করা উচিত এবং তারপরে প্যারামিটারগুলির সংখ্যা xargs -n দিয়ে নির্দিষ্ট করা উচিত।


হ্যাঁ আমাদের প্রোজেক্টে কেউ একই ধারণা পেয়েছে এবং এটি MSys এর সাথে উইন্ডোজ এর অধীনেও দুর্দান্ত কাজ করে।
গণিত

0

আমি উত্তর কিছু চেষ্টা। তারা যে স্ক্রিপ্টটি চেয়ে একটু বেশি জটিল করে তোলে। আদর্শভাবে ব্যবহার করা parallelবা xargsঅগ্রাধিকারযোগ্য হলেও লুপের জন্য ক্রিয়াকলাপ জটিল হলে এটি সমান্তরাল সরবরাহের জন্য একটি বড় এবং দীর্ঘ লাইন ফাইল তৈরি করতে সমস্যাযুক্ত হতে পারে। পরিবর্তে আমরা নিম্নরূপ উৎস ব্যবহার করতে পারে

# Create a test file 
$ cat test.txt
task_test 1
task_test 2

# Create a shell source file 
$ cat task.sh
task_test()
{
    echo $1
}

# use the source under bash -c 
$ cat test.txt | xargs -n1 -I{} bash -c 'source task.sh; {}'
1
2

সুতরাং আপনার সমস্যার সমাধানের জন্য দেখতে হবে

for i in *.myfiles; echo " do_something $i `derived_params $i` other_params
" >> commands.txt ; done

কিছু হিসাবে সংজ্ঞায়িত do_something.sh

do_something(){
process $1
echo $2 
whatever $3 

}

সঙ্গে চালানো xargবাgnu parallel

   cat commands.txt | xargs -n1 -I{} -P8 bash -c 'source do_something.sh; {}'

আমি implied জন্য পুনরাবৃত্তি কার্যকরী স্বাধীনতা অনুমান।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.