কীভাবে / কার্যকরী ভাষাগুলি (বিশেষত এরলং) স্কেল ভাল হয়?


92

আমি কিছুক্ষণের জন্য ক্রিয়ামূলক প্রোগ্রামিং ভাষা এবং বৈশিষ্ট্যগুলির ক্রমবর্ধমান দৃশ্যমানতাটি দেখছি। আমি সেগুলি সন্ধান করেছি এবং আবেদনের কারণ দেখিনি।

তারপরে, সম্প্রতি আমি কোডমাশে কেভিন স্মিথের " বেলিক্স অফ এরলং" উপস্থাপনাটিতে অংশ নিয়েছি

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

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

আমি বুঝতে পারি এরলংয়ের নির্মাতারা সম্মিলিত সমস্যাগুলি এড়াতে ইচ্ছাকৃতভাবে থ্রেডিং সমর্থন করা এড়িয়ে গেছেন, তবে আমি ভেবেছি স্কেলাবিলিটি অর্জনের জন্য মাল্টি-থ্রেডিং প্রয়োজনীয় ছিল।

ক্রিয়ামূলক প্রোগ্রামিং ভাষাগুলি কীভাবে অন্তর্নিহিতভাবে থ্রেড-নিরাপদ, তবুও স্কেল হতে পারে?


4
[উল্লিখিত নয়]: এরলংসের ভিএম অ্যাসিঙ্ক্রোনাসনেসকে অন্য স্তরে নিয়ে যায়। ভুডু যাদু (asm) দ্বারা এটি সকেটের মতো সিঙ্ক ক্রিয়াকলাপগুলিকে অনুমতি দেয়: কোনও ওএস থ্রেড না থামিয়ে ব্লক করতে পড়ুন। এটি আপনাকে সিঙ্ক্রোনাস কোড লেখার অনুমতি দেয় যখন অন্যান্য ভাষাগুলি আপনাকে এসিঙ্ক-কলব্যাক নেস্টে বাধ্য করে। আপনি যখনই কোড বেজে কিছুটা পরীক্ষা করে দেখেন তখন একক থ্রেডযুক্ত মাইক্রো-সার্ভিস ভিএস-এর মনের ছবি সহ একটি স্কেলিং অ্যাপটি লেখা খুব সহজ the
ভ্যান এস

@ ভ্যান এস আকর্ষণীয়।
জিম অ্যান্ডারসন

উত্তর:


99

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

এরলং একটি বার্তা পাসিং সিস্টেমে বেকিং দ্বারা এটি প্রচলিত ক্রিয়ামূলক ভাষার চেয়ে আরও বেশি এগিয়ে নিয়ে যায় যা ইভেন্ট ভিত্তিক সিস্টেমে সমস্ত কিছু পরিচালনা করতে দেয় যেখানে কোডের একটি টুকরো কেবল বার্তা প্রাপ্তি এবং বার্তাগুলি প্রেরণের বিষয়েই চিন্তিত করে, কোনও বড় ছবি নিয়ে চিন্তিত না।

এর অর্থ হ'ল প্রোগ্রামারটি (নামমাত্র) উদ্বেগহীন যে বার্তাটি অন্য কোনও প্রসেসর বা মেশিনে পরিচালিত হবে: কেবল বার্তা প্রেরণই এটি চালিয়ে যাওয়ার পক্ষে যথেষ্ট। যদি এটি কোনও প্রতিক্রিয়ার বিষয়ে চিন্তা করে তবে এটি অন্য বার্তা হিসাবে এটির জন্য অপেক্ষা করবে ।

এর শেষ ফলাফলটি হ'ল প্রতিটি স্নিপেট অন্য স্নিপেটের থেকে পৃথক। এএ ম্যাসেজ সিস্টেম থেকে আসা কোনও ভাগ করা কোড, কোনও ভাগ করা রাষ্ট্র এবং সমস্ত ক্রিয়াকলাপ যা অনেকগুলি হার্ডওয়ারের মধ্যে বিতরণ করা যায় (বা না)।

এটি একটি traditionalতিহ্যবাহী সিস্টেমের সাথে বিপরীতে: আমাদের "সুরক্ষিত" ভেরিয়েবল এবং কোড এক্সিকিউশন এর আশেপাশে মিটেক্সেস এবং সেমফোরাস রাখতে হবে। স্ট্যাকের মাধ্যমে একটি ফাংশন কলে আমাদের কাছে শক্ত বাইন্ডিং রয়েছে (ফিরে আসার অপেক্ষায়)। এগুলি সবই বাধা সৃষ্টি করে যা এরলংয়ের মতো ভাগ করা কিছুই নেই সিস্টেমে সমস্যা কম।

সম্পাদনা: আমার এও বোঝাতে হবে যে এরলং অবিচ্ছিন্ন ous আপনি আপনার বার্তাটি প্রেরণ করুন এবং সম্ভবত / কোনও দিন আবার অন্য বার্তা ফিরে আসে। অথবা না.

বাহ্যিক আদেশ কার্যকরকরণ সম্পর্কে স্পেনসারের বক্তব্যটিও গুরুত্বপূর্ণ এবং উত্তরের উত্তর।


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

4
আপনি একটি ভাগ করা কিছুই সিস্টেমে একাধিক সম্মতি সম্ভাবনা অর্জন। একটি খারাপ বাস্তবায়ন (উদাহরণস্বরূপ উচ্চ বার্তা ওভারহেড পেরিয়ে যাওয়া) এটিকে টর্পেডো করতে পারে তবে এরলং মনে হয় এটি সঠিক হয়ে উঠেছে এবং সবকিছুকে হালকা ওজন রাখবে।
গডেকে

এটি লক্ষণীয় গুরুত্বপূর্ণ যে এরল্যাংয়ের বার্তাগুলি শব্দার্থবিজ্ঞানের সময় এটির একটি ভাগ করে নেওয়া মেমরি বাস্তবায়ন রয়েছে, সুতরাং এটিতে শব্দার্থবিজ্ঞানের বর্ণনা রয়েছে তবে এটি না করতে পারলে এটি উভয় জায়গাতেই অনুলিপি করে না।
অ্যারন মেনপা

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

4
@ জোনহরপ প্রায় সঠিক: যখন কোনও প্রক্রিয়া অন্য কোনও প্রক্রিয়ায় একটি বার্তা পাঠায়, বার্তাটি অনুলিপি করা হয়; বড় বাইনারি বাদে, যা রেফারেন্স দ্বারা পাস করা হয়। এটি ভাল জিনিস কেন উদাহরণস্বরূপ jlouisramblings.blogspot.hu/2013/10/embrace-copying.html দেখুন ।
hcs42

74

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

r = methodWithALotOfDiskProcessing();
x = r + 1;
y = methodWithALotOfNetworkProcessing();
w = x * y

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

Execute line 1 ... wait.
Execute line 2 ... wait for r value.
Execute line 3 ... wait.
Execute line 4 ... wait for x and y value.
Line 3 returned ... y value set, message line 4.
Line 1 returned ... r value set, message line 2.
Line 2 returned ... x value set, message line 4.
Line 4 returned ... done.

কিভাবে শীতল হয়? কোডটি সামনে রেখে এবং কেবল যেখানে অপেক্ষা করার অপেক্ষা করে আমরা স্বয়ংক্রিয়ভাবে অপেক্ষার সময়টিকে দুই সেকেন্ডে কমিয়ে দিয়েছি! : ডি তাই হ্যাঁ, কোডটি সিঙ্ক্রোনাস হওয়ার সময় এটি পদ্ধতিগত ভাষাগুলির চেয়ে আলাদা অর্থ ধারণ করে।

সম্পাদনা:

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


কুল! বার্তা কীভাবে পরিচালনা করা হচ্ছে তা আমি পুরোপুরি ভুল বুঝেছিলাম। ধন্যবাদ, আপনার পোস্ট সাহায্য করে।
জিম অ্যান্ডারসন

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

16

সম্ভবত আপনি আপ মিশ করছি সমলয় সঙ্গে অনুক্রমিক

এরলং-এ কোনও ফাংশনের বডি ক্রমান্বয়ে প্রক্রিয়াজাত করা হচ্ছে। সুতরাং স্পেনসার এই "অটোমেজিকাল এফেক্ট" সম্পর্কে যা বলেছেন তা ঠিক ত্রুটিযুক্ত নয়। আপনি যদিও এরং এর সাথে এই আচরণটি মডেল করতে পারেন।

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

এইভাবে, আমরা এমন প্রসেসগুলিকে স্পেন করি যা "ভারী" গণনা করে (যদি পাওয়া যায় তবে অতিরিক্ত কোর ব্যবহার করে) এবং পরে আমরা ফলাফলগুলি সংগ্রহ করি।

-module(countwords).
-export([count_words_in_lines/1]).

count_words_in_lines(Lines) ->
    % For each line in lines run spawn_summarizer with the process id (pid)
    % and a line to work on as arguments.
    % This is a list comprehension and spawn_summarizer will return the pid
    % of the process that was created. So the variable Pids will hold a list
    % of process ids.
    Pids = [spawn_summarizer(self(), Line) || Line <- Lines], 
    % For each pid receive the answer. This will happen in the same order in
    % which the processes were created, because we saved [pid1, pid2, ...] in
    % the variable Pids and now we consume this list.
    Results = [receive_result(Pid) || Pid <- Pids],
    % Sum up the results.
    WordCount = lists:sum(Results),
    io:format("We've got ~p words, Sir!~n", [WordCount]).

spawn_summarizer(S, Line) ->
    % Create a anonymous function and save it in the variable F.
    F = fun() ->
        % Split line into words.
        ListOfWords = string:tokens(Line, " "),
        Length = length(ListOfWords),
        io:format("process ~p calculated ~p words~n", [self(), Length]),
        % Send a tuple containing our pid and Length to S.
        S ! {self(), Length}
    end,
    % There is no return in erlang, instead the last value in a function is
    % returned implicitly.
    % Spawn the anonymous function and return the pid of the new process.
    spawn(F).

% The Variable Pid gets bound in the function head.
% In erlang, you can only assign to a variable once.
receive_result(Pid) ->
    receive
        % Pattern-matching: the block behind "->" will execute only if we receive
        % a tuple that matches the one below. The variable Pid is already bound,
        % so we are waiting here for the answer of a specific process.
        % N is unbound so we accept any value.
        {Pid, N} ->
            io:format("Received \"~p\" from process ~p~n", [N, Pid]),
            N
    end.

এবং আমরা এটি শেলটিতে চালানোর সময় এটির মতো দেখতে লাগে:

Eshell V5.6.5  (abort with ^G)
1> Lines = ["This is a string of text", "and this is another", "and yet another", "it's getting boring now"].
["This is a string of text","and this is another",
 "and yet another","it's getting boring now"]
2> c(countwords).
{ok,countwords}
3> countwords:count_words_in_lines(Lines).
process <0.39.0> calculated 6 words
process <0.40.0> calculated 4 words
process <0.41.0> calculated 3 words
process <0.42.0> calculated 4 words
Received "6" from process <0.39.0>
Received "4" from process <0.40.0>
Received "3" from process <0.41.0>
Received "4" from process <0.42.0>
We've got 17 words, Sir!
ok
4> 

13

এরলংকে স্কেল করতে সক্ষম করে এমন মূল জিনিসটি চুক্তির সাথে সম্পর্কিত।

একটি অপারেটিং সিস্টেম দুটি প্রক্রিয়া দ্বারা সম্মতি প্রদান করে:

  • অপারেটিং সিস্টেম প্রক্রিয়াগুলি
  • অপারেটিং সিস্টেম থ্রেড

প্রক্রিয়াগুলি রাষ্ট্র ভাগ করে না - একটি প্রক্রিয়া অন্য ডিজাইন দ্বারা ক্র্যাশ করতে পারে না।

থ্রেডগুলি ভাগ করে নেওয়ার স্টেট - একটি থ্রেড অন্য ডিজাইন দ্বারা ক্র্যাশ করতে পারে - এটাই আপনার সমস্যা।

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

এই ইরালং প্রক্রিয়া বার্তা প্রেরণে একে অপরের সাথে কথা বলে (অপারেটিং সিস্টেম নয় বরং এরলং ভিএম পরিচালনা করে) এরলং প্রসেস আইডি (পিআইডি) ব্যবহার করে একে অপরকে সম্বোধন করে যার তিন ভাগের ঠিকানা রয়েছে <<N3.N2.N1>>:

  • কোনও এন 1 প্রক্রিয়া না
  • ভিএম এন 2 চালু
  • শারীরিক যন্ত্র N3

একই মেশিনে একই ভিএম-তে দুটি প্রক্রিয়া, একই মেশিনে বিভিন্ন ভিএম বা দুটি মেশিন একইভাবে যোগাযোগ করে - আপনার স্কেলিং অতএব আপনি যে অ্যাপ্লিকেশনটি প্রয়োগ করেন তার প্রথম সংখ্যা (প্রথম আনুমানিকভাবে) এর চেয়ে স্বাধীন।

ত্রুটিপূর্ণ অর্থে এয়ারলং কেবল থ্রেডসফ - এটির থ্রেড নেই। (যে ভাষাটি হ'ল, এসএমপি / মাল্টি-কোর ভিএম প্রতিটি প্রতি এক অপারেটিং সিস্টেম থ্রেড ব্যবহার করে)।


7

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


4

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

দেখে মনে হচ্ছে আপনি ক্রিসের উল্লিখিত হিসাবে সিঙ্ক্রোনাস এবং ক্রমিক হিসাবে মিশ্রিত করেছেন।



-2

বিশুদ্ধভাবে কার্যকরী ভাষায়, মূল্যায়নের ক্রমের কোনও গুরুত্ব নেই - একটি ফাংশন অ্যাপ্লিকেশন fn (arg1, .. argn) এ, এন আর্গুমেন্টগুলি সমান্তরালভাবে মূল্যায়ন করা যেতে পারে। এটি একটি উচ্চ স্তরের (স্বয়ংক্রিয়) সমান্তরালতার গ্যারান্টি দেয়।

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

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