কেন এই এফ # কোডটি এত ধীর?


127

সি # এবং এফ # তে একটি লেভেনস্টেইন বাস্তবায়ন। সি # সংস্করণটি প্রায় 1500 চরগুলির দুটি স্ট্রিংয়ের জন্য 10 গুণ দ্রুত। সি #: 69 এমএস, এফ # 867 এমএস কেন? আমি যতদূর বলতে পারি, তারা ঠিক একই কাজ করে? এটি রিলিজ বা ডিবাগ বিল্ড কিনা তা বিবেচ্য নয়।

সম্পাদনা: যদি কেউ এখানে এসে বিশেষত সম্পাদনা করুন দূরত্ব বাস্তবায়নটির জন্য সন্ধান করেন, এটি ভেঙে গেছে। ওয়ার্কিং কোড এখানে

সি # :

private static int min3(int a, int b, int c)
{
   return Math.Min(Math.Min(a, b), c);
}

public static int EditDistance(string m, string n)
{
   var d1 = new int[n.Length];
   for (int x = 0; x < d1.Length; x++) d1[x] = x;
   var d0 = new int[n.Length];
   for(int i = 1; i < m.Length; i++)
   {
      d0[0] = i;
      var ui = m[i];
      for (int j = 1; j < n.Length; j++ )
      {
         d0[j] = 1 + min3(d1[j], d0[j - 1], d1[j - 1] + (ui == n[j] ? -1 : 0));
      }
      Array.Copy(d0, d1, d1.Length);
   }
   return d0[n.Length - 1];
}

এফ # :

let min3(a, b, c) = min a (min b c)

let levenshtein (m:string) (n:string) =
   let d1 = Array.init n.Length id
   let d0 = Array.create n.Length 0
   for i=1 to m.Length-1 do
      d0.[0] <- i
      let ui = m.[i]
      for j=1 to n.Length-1 do
         d0.[j] <- 1 + min3(d1.[j], d0.[j-1], d1.[j-1] + if ui = n.[j] then -1 else 0)
      Array.blit d0 0 d1 0 n.Length
   d0.[n.Length-1]

7
ইনলাইন ব্যবহার করে পারফরম্যান্সের পার্থক্য কী?
গ্রেডবোট

উত্তর:


202

সমস্যাটি হ'ল min3ফাংশনটি জেনেরিক ফাংশন হিসাবে সংকলিত যা জেনেরিক তুলনা ব্যবহার করে (আমি ভেবেছিলাম IComparableএটি কেবলমাত্র ব্যবহার করে তবে এটি আসলে আরও জটিল - এটি F # প্রকারের জন্য কাঠামোগত তুলনা ব্যবহার করবে এবং এটি মোটামুটি জটিল যুক্তিযুক্ত হবে)।

> let min3(a, b, c) = min a (min b c);;
val min3 : 'a * 'a * 'a -> 'a when 'a : comparison

সি # সংস্করণে, ফাংশনটি জেনেরিক নয় (এটি কেবল নেয় int)। আপনি টাইপ টীকাগুলি যুক্ত করে এফ # সংস্করণটি উন্নত করতে পারেন (সি # তে একই জিনিস পেতে):

let min3(a:int, b, c) = min a (min b c)

... বা min3হিসাবে তৈরি করে inline(কোন ক্ষেত্রে এটি ব্যবহারের ক্ষেত্রে বিশেষীকরণ করা হবে int):

let inline min3(a, b, c) = min a (min b c);;

str300 দৈর্ঘ্যের এলোমেলো স্ট্রিংয়ের জন্য, আমি নিম্নলিখিত সংখ্যাগুলি পেয়েছি:

> levenshtein str ("foo" + str);;
Real: 00:00:03.938, CPU: 00:00:03.900, GC gen0: 275, gen1: 1, gen2: 0
val it : int = 3

> levenshtein_inlined str ("foo" + str);;
Real: 00:00:00.068, CPU: 00:00:00.078, GC gen0: 0, gen1: 0, gen2: 0
val it : int = 3

1
কেন F # কমপক্ষে একটি ক্রিয়াকলাপ হিসাবে min3 সংকলন করে না? এটি করার জন্য এটি কমপাইল সময়ে পর্যাপ্ত ধরনের তথ্য ইতিমধ্যে জানে। এইভাবে এটি কাজ করবে যদি মিনি 3 একটি সি ++ টেম্পলেট ফাংশন ছিল, তাই আমি কেন এফ # এটি না করে তা নিয়ে আমি কিছুটা বিস্মিত হই।
শাশং

42
এফ # এটি যথাসম্ভব জেনেরিক হিসাবে অনুভূত করে, যেমন "সমস্ত ধরণের এক্সের জন্য যা তুলনা সমর্থন করে"। inlineসি ++ টেমপ্লেটের মতো কাজ intকরে যা কল সাইটের উপর ভিত্তি করে বিশেষ করে ।
ব্রায়ান

13
সি ++ টেমপ্লেটগুলি এফ # এর হিসাবে মূলত আচরণ করে inline। ডিফল্ট আচরণের আলাদা হওয়ার কারণ হ'ল এটি তৈরি করে। এফ # তে সি ++ ব্যবহারের ফলে কোড ব্লাট হতে পারে, কারণ এফ # জেনেরিকগুলি আরও অনেক কিছু ব্যবহার করে।
টমাস পেট্রিসেক

4
সি ++ টেম্পলেট শব্দার্থবিজ্ঞানগুলি সি ++ তেও কোড ব্লাট হতে পারে এবং এটি এড়ানোর জন্য রান-টাইম মেকানিজম ব্যবহারে স্যুইচ করার কোনও সুবিধাজনক পদ্ধতির অভাব কখনও কখনও ঝামেলা হতে পারে। তবে কোড ব্লোটের ভয়টি সাধারণত অযৌক্তিক - সাধারণত, সি ++ টেম্পলেটগুলি ভালভাবে কাজ করে।
স্টিভ 314

@ স্টিভ ৩১৪: নির্ভরশীল ধরণের ব্যবহার না করে এমন সমস্ত কোডের পুনরায় ব্যবহারের মাধ্যমে এড়ানো সাধারণত সহজ হয়, যাতে সেই কোডটি বিভিন্ন ইনস্ট্যানটিশনের জন্য সদৃশ হয় না।
iljarn
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.