সি, ক্লোজার, পাইথন, রুবি, স্কালা এবং অন্যান্যগুলিতে একটি মানদণ্ডের ব্যাখ্যা করা [বন্ধ]


91

অস্বীকৃতি

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

গণিতের মানদণ্ডের বর্ণনা

বেঞ্চমার্ক হ'ল গণিতের গণনা যা প্রধান সংখ্যাগুলির জোড়গুলি খুঁজে বের করে যা 6 দ্বারা পৃথক হয় (তথাকথিত সেক্সি প্রাইমস ) উদাহরণস্বরূপ 100 এর নীচে সেক্সি প্রাইমগুলি হ'ল:(5 11) (7 13) (11 17) (13 19) (17 23) (23 29) (31 37) (37 43) (41 47) (47 53) (53 59) (61 67) (67 73) (73 79) (83 89) (97 103)

ফলাফলের টেবিল

সারণীতে: সেকেন্ডে গণনার সময় চলমান: ফ্যাক্টর ব্যতীত অন্য সমস্ত ভার্চুয়ালবক্সে চলছিল (ডিবিয়ান অস্থির amd64 অতিথি, উইন্ডোজ 7 x64 হোস্ট) সিপিইউ: এএমডি এ 4-3305 এম

  Sexy primes up to:        10k      20k      30k      100k               

  Bash                    58.00   200.00     [*1]      [*1]

  C                        0.20     0.65     1.42     15.00

  Clojure1.4               4.12     8.32    16.00    137.93

  Clojure1.4 (optimized)   0.95     1.82     2.30     16.00

  Factor                    n/a      n/a    15.00    180.00

  Python2.7                1.49     5.20    11.00       119     

  Ruby1.8                  5.10    18.32    40.48    377.00

  Ruby1.9.3                1.36     5.73    10.48    106.00

  Scala2.9.2               0.93     1.41     2.73     20.84

  Scala2.9.2 (optimized)   0.32     0.79     1.46     12.01

[* 1] - কত সময় লাগবে তা ভেবে ভীত আমি

কোড তালিকা

সি:

int isprime(int x) {
  int i;
  for (i = 2; i < x; ++i)
    if (x%i == 0) return 0;
  return 1;
}

void findprimes(int m) {
  int i;
  for ( i = 11; i < m; ++i)
    if (isprime(i) && isprime(i-6))
      printf("%d %d\n", i-6, i);
}

main() {
    findprimes(10*1000);
}

রুবি:

def is_prime?(n)
  (2...n).all?{|m| n%m != 0 }
end

def sexy_primes(x)
  (9..x).map do |i|
    [i-6, i]
  end.select do |j|
    j.all?{|j| is_prime? j}
  end
end

a = Time.now
p sexy_primes(10*1000)
b = Time.now
puts "#{(b-a)*1000} mils"

স্কেল:

def isPrime(n: Int) =
  (2 until n) forall { n % _ != 0 }

def sexyPrimes(n: Int) = 
  (11 to n) map { i => List(i-6, i) } filter { _ forall(isPrime(_)) }

val a = System.currentTimeMillis()
println(sexyPrimes(100*1000))
val b = System.currentTimeMillis()
println((b-a).toString + " mils")

স্কেলা অপিমাইজড isPrime( ক্লোজার অপ্টিমাইজেশানের মতো একই ধারণা):

import scala.annotation.tailrec

@tailrec // Not required, but will warn if optimization doesn't work
def isPrime(n: Int, i: Int = 2): Boolean = 
  if (i == n) true 
  else if (n % i != 0) isPrime(n, i + 1)
  else false

ক্লোজার:

(defn is-prime? [n]
  (every? #(> (mod n %) 0)
    (range 2 n)))

(defn sexy-primes [m]
  (for [x (range 11 (inc m))
        :let [z (list (- x 6) x)]
        :when (every? #(is-prime? %) z)]
      z))

(let [a (System/currentTimeMillis)]
  (println (sexy-primes (* 10 1000)))
  (let [b (System/currentTimeMillis)]
    (println (- b a) "mils")))

ক্লোজার অপ্টিমাইজড is-prime?:

(defn ^:static is-prime? [^long n]
  (loop [i (long 2)] 
    (if (= (rem n i) 0)
      false
      (if (>= (inc i) n) true (recur (inc i))))))

পাইথন

import time as time_

def is_prime(n):
  return all((n%j > 0) for j in xrange(2, n))

def primes_below(x):
  return [[j-6, j] for j in xrange(9, x+1) if is_prime(j) and is_prime(j-6)]

a = int(round(time_.time() * 1000))
print(primes_below(10*1000))
b = int(round(time_.time() * 1000))
print(str((b-a)) + " mils")

ফ্যাক্টর

MEMO:: prime? ( n -- ? )
n 1 - 2 [a,b] [ n swap mod 0 > ] all? ;

MEMO: sexyprimes ( n n -- r r )
[a,b] [ prime? ] filter [ 6 + ] map [ prime? ] filter dup [ 6 - ] map ;

5 10 1000 * sexyprimes . .

বাশ (zsh):

#!/usr/bin/zsh
function prime {
  for (( i = 2; i < $1; i++ )); do
    if [[ $[$1%i] == 0 ]]; then
      echo 1
      exit
    fi
  done
  echo 0
}

function sexy-primes {
  for (( i = 9; i <= $1; i++ )); do
    j=$[i-6]
    if [[ $(prime $i) == 0 && $(prime $j) == 0 ]]; then
      echo $j $i
    fi
  done
}

sexy-primes 10000

প্রশ্ন

  1. স্কেলা এত দ্রুত কেন? এটি কি স্থির টাইপিংয়ের কারণে ? অথবা এটি খুব কার্যকরভাবে জেভিএম ব্যবহার করছে?
  2. রুবি এবং পাইথনের মধ্যে এত বড় পার্থক্য কেন? আমি ভেবেছিলাম এই দুটি কিছুটা সম্পূর্ণ আলাদা নয়। আমার কোডটি ভুল হতে পারে। আমাকে আলোকিত করুন! ধন্যবাদ ইউপিডি হ্যাঁ, এটি আমার কোডে ত্রুটি ছিল। পাইথন এবং রুবি 1.9 বেশ সমান।
  3. রুবি সংস্করণগুলির মধ্যে উত্পাদনশীলতায় সত্যই চিত্তাকর্ষক লাফ।
  4. আমি কি ধরণের ঘোষণা যুক্ত করে ক্লোজার কোডটি অনুকূল করতে পারি? এটা সাহায্য করবে?

6
@ মিগিলসন আসলে পর্যন্ত sqrt(n)তবে এটি গণনা করতে কিছুটা সময় নিতে পারে। এছাড়াও আপনার সি কোডগুলি প্রাইমগুলি খুঁজে পাওয়ার সাথে সাথে এটি মুদ্রণ করে, যেখানে আপনার অন্যান্য ভাষাগুলি সেগুলিকে তালিকায় গণনা করে এবং পরে সেগুলি মুদ্রণ করে। যদিও সি আশ্চর্যজনকভাবে দ্রুততম, আপনি এটি আরও দ্রুত পেতে সক্ষম হতে পারেন।
রাশি

4
(এবং অবশ্যই এরাটোস্থেনিস এর চালনী .. কিন্তু এই মাইক্রো বেঞ্চমার্ক প্রায় কাছাকাছি পুনরাবৃত্তির ও গণিত অপারেশনের চাপ পরীক্ষা যাইহোক, তারা এখনও "ন্যায্য" হয় হিসাবে আরো কিছু অলস।।)

4
আমি কেবল আমার গো সংস্করণ এবং আপনার সি সংস্করণ উভয়ই চালিয়েছি (এটি দেখতে অনেকটা একই রকম) এবং আমি উভয়টিতেই কার্যত একই গতি পেয়েছি। আমি শুধুমাত্র 100 কিলোবাইট সংস্করণ চেষ্টা: C: 2.723s Go: 2.743s
সেবাস্তিয়ান গ্রিগনোলি

4
sqrtএই চেকটির জন্য আপনাকে গণনা করার দরকার নেই । আপনি iযেমন হিসাবে বর্গাকার গণনা করতে পারেনfor (i = 2; i * i <= x; ++i) ...
ivant

4
আপনি লেজ পুনরাবৃত্তি ব্যবহার করছেন তা নিশ্চিত করার জন্য আমি আপনাকে স্কালার isPrimeসাথে অনুকূলিতকরণ বিকাশ করার পরামর্শ দিচ্ছি @tailrec। লেজ পুনরাবৃত্তি রোধ করে এমন কিছু ভুল করে করা সহজ এবং যদি এরকম ঘটে থাকে তবে এই টীকাটি আপনাকে সতর্ক করে।
ড্যানিয়েল সি। সোব্রাল

উত্তর:


30

রুক্ষ উত্তর:

  1. স্কেলার স্থিতিশীল টাইপিং এটি এখানে বেশ খানিকটা সহায়তা করছে - এর অর্থ এটি অত্যধিক অতিরিক্ত প্রচেষ্টা ছাড়াই JVM কে বেশ দক্ষতার সাথে ব্যবহার করে।
  2. আমি রুবি / পাইথন পার্থক্য সম্পর্কে ঠিক নিশ্চিত নই, তবে আমি সন্দেহ করি যে (2...n).all?ফাংশনটি is-prime?রুবিতে বেশ ভালভাবে অনুকূলিত হওয়ার সম্ভাবনা রয়েছে (এডিআইটি: শোনাচ্ছে এটি সত্যই এরকম, আরও বিস্তারিত জানার জন্য জুলিয়ান এর উত্তর দেখুন ...)
  3. রুবি 1.9.3 আরও অনেক বেশি অনুকূলিত optim
  4. ক্লোজার কোডটি অবশ্যই অনেক বেশি ত্বরান্বিত হতে পারে! Clojure যখন ডিফল্টরূপে গতিশীল, আপনি যখন প্রয়োজন হয় তখন স্ক্যালার / খাঁটি জাভা গতির কাছাকাছি যেতে আপনি টাইপ ইঙ্গিত, আদিম গণিত ইত্যাদি ব্যবহার করতে পারেন।

ক্লোজার কোডটিতে সর্বাধিক গুরুত্বপূর্ণ অপটিমাইজেশন হ'ল টাইপের আদিম গণিতের মধ্যে ব্যবহার করা is-prime?যেমন:

(set! *unchecked-math* true) ;; at top of file to avoid using BigIntegers

(defn ^:static is-prime? [^long n]
  (loop [i (long 2)] 
    (if (zero? (mod n i))
      false
      (if (>= (inc i) n) true (recur (inc i))))))

এই উন্নতির সাথে, আমি ক্লোজার পেয়েছি 10 ক 0 0353 সেকেন্ডে সমাপ্ত (যেমন আপনার তালিকার দ্বিতীয় দ্রুততম, স্কালাকে হারিয়ে)

পিএস নোট করুন যে কিছু ক্ষেত্রে আপনার বেঞ্চমার্কের ভিতরে আপনার মুদ্রণ কোড রয়েছে - এটি ভাল ধারণা নয় কারণ এটি ফলাফলকে বিকৃত করে দেবে, বিশেষত যদি printপ্রথমবারের মতো কোনও ফাংশন ব্যবহার করা আইও সাবসিস্টেমের সূচনা বা এরকম কোনও কিছুর কারণ হয়!


4
আমি মনে করি না যে রুবি এবং পাইথন সম্পর্কে বিটটি অগত্যা সত্য, তবে +1 অন্যথায় ..

টাইপিং কোনও পরিমাপযোগ্য স্থিতিশীল ফলাফল is-prime?দেখায় নি, তবে আপনার নতুন শোতে 2x উন্নতি হয়েছে। ;)
ডিফ্ল্ট করুন

যদি একটি চেক না করা-মোড থাকে তবে এটিকে কী আর দ্রুত করা যায় না?
হেন্ডেকাগন

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

4
(zero? (mod n i))এর চেয়ে দ্রুত হওয়া উচিত(= (mod n i) 0)
জোনাস

23

একই বেসিক অ্যালগরিদম ব্যবহার করে এখানে একটি দ্রুত ক্লোজার সংস্করণ রয়েছে:

(set! *unchecked-math* true)

(defn is-prime? [^long n]
  (loop [i 2]
    (if (zero? (unchecked-remainder-int n i))
      false
      (if (>= (inc i) n)
        true
        (recur (inc i))))))

(defn sexy-primes [m]
  (for [x (range 11 (inc m))
        :when (and (is-prime? x) (is-prime? (- x 6)))]
    [(- x 6) x]))

এটি আমার মেশিনে আপনার মূলের চেয়ে প্রায় 20x দ্রুত চলে। এবং এখানে এমন একটি সংস্করণ রয়েছে যা 1.5 এ নতুন হ্রাসকারী গ্রন্থাগারটি লাভ করে (জাভা 7 বা জেএসআর 166 প্রয়োজন):

(require '[clojure.core.reducers :as r]) ;'

(defn sexy-primes [m]
  (->> (vec (range 11 (inc m)))
       (r/filter #(and (is-prime? %) (is-prime? (- % 6))))
       (r/map #(list (- % 6) %))
       (r/fold (fn ([] []) ([a b] (into a b))) conj)))

এটি আপনার আসল থেকে প্রায় 40x দ্রুত চলে। আমার মেশিনে, এটি 1.5 সেকেন্ডের মধ্যে 100k।


4
স্থিতিশীল টাইপিংয়ের সাথে 4x কার্যকারিতা বৃদ্ধির পরিবর্তে ব্যবহার unchecked-remainder-intবা কেবল remপরিবর্তে modসুন্দর!
ডিফ্ল্ট করুন

22

আমি মাত্র # 2 জবাব দেব, যেহেতু এটিই কেবলমাত্র আমার কাছে দূরবর্তীভাবে বুদ্ধিমান কিছু বলতে পেরেছিল তবে আপনার পাইথন কোডের জন্য আপনি একটি মধ্যবর্তী তালিকা তৈরি করছেন is_prime, যেখানে আপনি রুবিতে .mapআপনার ব্যবহার করছেন allযা ঠিক পুনরাবৃত্তি।

আপনি যদি এতে পরিবর্তন is_primeকরেন:

def is_prime(n):
    return all((n%j > 0) for j in range(2, n))

তারা সমান

আমি পাইথনকে আরও অনুকূলিত করতে পারি, তবে আমার রুবি কখন আরও বেশি সুবিধা দিয়েছি তা জানার পক্ষে যথেষ্ট নয় (যেমন, ব্যবহার করে xrange করে আমার মেশিনে পাইথনকে জিতিয়েছে, তবে আপনি যে রুবি ব্যাপ্তি ব্যবহার করেছেন তা তৈরি করে কিনা তা আমার মনে নেই) স্মৃতিতে একটি সম্পূর্ণ পরিসীমা বা না)।

সম্পাদনা: খুব নিরীহ না হয়ে পাইথন কোডটি এমন দেখাচ্ছে:

import time

def is_prime(n):
    return all(n % j for j in xrange(2, n))

def primes_below(x):
    return [(j-6, j) for j in xrange(9, x + 1) if is_prime(j) and is_prime(j-6)]

a = int(round(time.time() * 1000))
print(primes_below(10*1000))
b = int(round(time.time() * 1000))
print(str((b-a)) + " mils")

যা আরও বেশি কিছু পরিবর্তন করে না, আমার জন্য এটি 1.5 সেকেন্ড রাখে এবং অতিরিক্ত নির্বোধ হওয়ার সাথে সাথে পাইপির সাথে চালানো এটি 10 ​​কে এর জন্য .3 এস এবং 100 কে জন্য 21 সেকেন্ডে রাখে।


4
জেনারেটরটি এখানে একটি বড় পার্থক্য করে কারণ এটি ফাংশনটিকে প্রথমটিতে False(ভাল ক্যাচ) জামিন দেওয়ার অনুমতি দেয় ।
মিগিলসন

আমি সত্যিই তাদের পিপিপিতে অলস হয়ে উঠার অপেক্ষায় রয়েছি ... এটি দুর্দান্ত হতে চলেছে।
মিগিলসন

আপনি কি দয়া করে আমার উত্তর পিপাইতে চালাবেন? আমি কৌতুহল যে কত দ্রুত হবে।
স্টিভাহ

4
আপনি পুনরাবৃত্তি জিনিস এবং উভয় সম্পর্কে সম্পূর্ণরূপে সঠিক xrange! আমি স্থির করেছি এবং এখন পাইথন এবং রুবি সমান ফলাফল দেখায়।
ডিফ্ল্ট করুন

4
@ ধীরে ধীরে আমি কেবল তখনই তা করবো যদি আপনি এখনই বাইরে যান এবং নিজে পিপিপি ডাউনলোড করবেন বলে প্রতিশ্রুতি দেন :)! pypy.org/download.html সমস্ত সাধারণ ওএসের জন্য বাইনারি থাকে এবং আপনার প্যাকেজ ম্যানেজার নিঃসন্দেহে এটি থাকে। যাইহোক, আপনার বেঞ্চমার্ক হিসাবে, lru_cacheAS এ পাওয়া 2.7 এর এলোমেলো বাস্তবায়ন সহ , 100 কে ২.৩ এর মধ্যে রান করে।
জুলিয়ান

16

আপনি নিজের isPrimeপদ্ধতিতে পরিবর্তন করে স্ক্যালাকে আরও দ্রুত তৈরি করতে পারেন

  def isPrime(n: Int, i: Int = 2): Boolean = 
    if (i == n) true 
    else if (n % i != 0) isPrime(n, i + 1)
    else false

যথেষ্ট হিসাবে সংক্ষিপ্ত নয় তবে প্রোগ্রামটি 40% সময়ের মধ্যে চলে!

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

আরও দেখুন: স্কালায় বোঝাপড়া এবং লুপগুলি কীভাবে অনুকূল করা যায়?


4
2x উন্নতি। এবং দুর্দান্ত লিঙ্ক!
Defhlt

বিটিডব্লিউ এই পদ্ধতির বডিটি একইরকম i == n || n % i != 0 && isPrime(n, i + 1), যা খাটো, যদিও পড়া কিছুটা কঠিন
লুইজি প্লিঞ্জ

4
আপনার সেই @tailrecমন্তব্যটি যুক্ত করা উচিত ছিল তা নিশ্চিত করার জন্য এটি সেই অপ্টিমাইজেশান তৈরি করবে।
ড্যানিয়েল সি সোব্রাল

8

এখানে আমার স্কাল সংস্করণটি সমান্তরাল এবং ন-সমান্তরাল উভয় ক্ষেত্রেই রয়েছে কেবল মজাদার জন্য: (আমার দ্বৈত কোর গণিতে, সমান্তরাল সংস্করণটি 335 মিমি লাগে যখন ন-সমান্তরাল সংস্করণ 655 মিমি লাগে)

object SexyPrimes {
  def isPrime(n: Int): Boolean = 
    (2 to math.sqrt(n).toInt).forall{ n%_ != 0 }

  def isSexyPrime(n: Int): Boolean = isPrime(n) && isPrime(n-6)

  def findPrimesPar(n: Int) {
    for(k <- (11 to n).par)
      if(isSexyPrime(k)) printf("%d %d\n",k-6,k)
  }

  def findPrimes(n: Int) {
    for(k <- 11 to n)
      if(isSexyPrime(k)) printf("%d %d\n",k-6,k)
  }


  def timeOf(call : =>Unit) {
    val start = System.currentTimeMillis
    call
    val end = System.currentTimeMillis
    println((end-start)+" mils")
  }

  def main(args: Array[String]) {
    timeOf(findPrimes(100*1000))
    println("------------------------")
    timeOf(findPrimesPar(100*1000))
  }
}

সম্পাদনা: এমিল এইচ এর পরামর্শ অনুসারে, আইও এবং জেভিএম ওয়ার্মআপের প্রভাব এড়াতে আমি আমার কোড পরিবর্তন করেছি:

ফলাফলটি আমার গণনাতে দেখায়:

তালিকা (3432, 1934, 3261, 1716, 3229, 1654, 3214, 1700)

object SexyPrimes {
  def isPrime(n: Int): Boolean = 
    (2 to math.sqrt(n).toInt).forall{ n%_ != 0 }

  def isSexyPrime(n: Int): Boolean = isPrime(n) && isPrime(n-6)

  def findPrimesPar(n: Int) {
    for(k <- (11 to n).par)
      if(isSexyPrime(k)) ()//printf("%d %d\n",k-6,k)
  }

  def findPrimes(n: Int) {
    for(k <- 11 to n)
      if(isSexyPrime(k)) ()//printf("%d %d\n",k-6,k)
  }


  def timeOf(call : =>Unit): Long = {
    val start = System.currentTimeMillis
    call
    val end = System.currentTimeMillis
    end - start 
  }

  def main(args: Array[String]) {
    val xs = timeOf(findPrimes(1000*1000))::timeOf(findPrimesPar(1000*1000))::
             timeOf(findPrimes(1000*1000))::timeOf(findPrimesPar(1000*1000))::
             timeOf(findPrimes(1000*1000))::timeOf(findPrimesPar(1000*1000))::
             timeOf(findPrimes(1000*1000))::timeOf(findPrimesPar(1000*1000))::Nil
    println(xs)
  }
}

4
কোডটি কী জেভিএম ওয়ার্মআপ দ্বারা প্রভাবিত হয়েছে? উদাহরণস্বরূপ isSexyPrimeযখন ডাকা হবে তখন আরও (আরও) অনুকূলিত হতে পারে findPrimesParএবং যখন ফোন করা হয় তখন এতটা নাfindPrimes
এমিল এইচ

@ এমিলহহ ফেয়ার যথেষ্ট। আইও এবং জেভিএম ওয়ার্মআপের প্রভাব এড়াতে আমি আমার কোড পরিবর্তন করেছি।
ইস্টসুন

কেবল স্কয়ার্ট (এন) এ যাওয়া ভাল অপটিমাইজেশন, তবে আপনি এখন একটি আলাদা অ্যালগরিদম বেঞ্চমার্ক করছেন।
লুইজি প্লিঞ্জ

7

মানদণ্ডকে কখনই মনে করবেন না; সমস্যাটি আমাকে আগ্রহী করে তুলেছিল এবং আমি কিছু দ্রুত টুইটগুলি করেছি। এটি lru_cacheসাজসজ্জার ব্যবহার করে , যা কোনও ফাংশনকে স্মরণ করে; সুতরাং আমরা যখন কল is_prime(i-6)করি তখন আমরা মূলত বিনামূল্যে সেই প্রাইম চেকটি পাই। এই পরিবর্তনটি প্রায় অর্ধেকে কাজটি কেটে দেয়। এছাড়াও, আমরা range()কলগুলি কেবল বিজোড় সংখ্যাগুলির মধ্যে দিয়ে ধাপে ধাপে কাজটি আবার প্রায় অর্ধেকে কেটে দিতে পারি।

http://en.wikedia.org/wiki/Memoization

http://docs.python.org/dev/library/functools.html

এটি পেতে পাইথন 3.2 বা আরও নতুন প্রয়োজন lru_cache, তবে আপনি যদি পাইথন রেসিপি সরবরাহ করে তবে এটি পুরানো পাইথনের সাথে কাজ করতে পারে lru_cache। আপনি যদি পাইথন ২.x ব্যবহার করেন তবে এর xrange()পরিবর্তে আপনার ব্যবহার করা উচিত range()

http://code.activestate.com/recines/577479-simple-caching-decorator/

from functools import lru_cache
import time as time_

@lru_cache()
def is_prime(n):
    return n%2 and all(n%i for i in range(3, n, 2))

def primes_below(x):
    return [(i-6, i) for i in range(9, x+1, 2) if is_prime(i) and is_prime(i-6)]

correct100 = [(5, 11), (7, 13), (11, 17), (13, 19), (17, 23), (23, 29),
        (31, 37), (37, 43), (41, 47), (47, 53), (53, 59), (61, 67), (67, 73),
        (73, 79), (83, 89)]
assert(primes_below(100) == correct100)

a = time_.time()
print(primes_below(30*1000))
b = time_.time()

elapsed = b - a
print("{} msec".format(round(elapsed * 1000)))

উপরেরগুলি সম্পাদনা করতে খুব কম সময় নিয়েছিল। আমি এটিকে আরও একধাপ এগিয়ে নিয়ে যাওয়ার সিদ্ধান্ত নিয়েছি এবং প্রাইমস পরীক্ষাটি কেবলমাত্র প্রাথমিক বিভাজনকারীদের চেষ্টা করব এবং কেবলমাত্র সংখ্যার বর্গমূল পর্যন্ত পরীক্ষা করা হচ্ছে। আমি যেভাবে এটি করেছি কেবলমাত্র আপনি যদি ক্রম সংখ্যা পরীক্ষা করে দেখেন তবে এটি সমস্ত প্রাইমগুলিকে যেমন যায় তেমন সংগ্রহ করতে পারে; তবে এই সমস্যাটি আগে থেকেই সংখ্যাগুলি পরীক্ষা করে দেখছিল যাতে তা ঠিক ছিল।

আমার ল্যাপটপে (বিশেষ কিছু নয়; প্রসেসরটি 1.5 গিগাহার্টজ এএমডি তুরিয়ন II "কে 625") এই সংস্করণটি 100 সেকেন্ডের জন্য 8 সেকেন্ডের মধ্যে একটি উত্তর তৈরি করে।

from functools import lru_cache
import math
import time as time_

known_primes = set([2, 3, 5, 7])

@lru_cache(maxsize=128)
def is_prime(n):
    last = math.ceil(math.sqrt(n))
    flag = n%2 and all(n%x for x in known_primes if x <= last)
    if flag:
        known_primes.add(n)
    return flag

def primes_below(x):
    return [(i-6, i) for i in range(9, x+1, 2) if is_prime(i) and is_prime(i-6)]

correct100 = [(5, 11), (7, 13), (11, 17), (13, 19), (17, 23), (23, 29),
        (31, 37), (37, 43), (41, 47), (47, 53), (53, 59), (61, 67), (67, 73),
        (73, 79), (83, 89)]
assert(primes_below(100) == correct100)

a = time_.time()
print(primes_below(100*1000))
b = time_.time()

elapsed = b - a
print("{} msec".format(round(elapsed * 1000)))

উপরের কোডটি পাইথন, রুবি ইত্যাদিতে লেখা খুব সহজ তবে এটি সি এর ব্যথা বেশি হবে would

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


lru_cacheঅবশ্যই নিফটি। ক্রমবর্ধমান ফিবোনাচি সংখ্যা তৈরির মতো কিছু নির্দিষ্ট শ্রেণীর সমস্যার জন্য, এটি কেবলমাত্র ফাংশনে একটি লাইন ডেকরেটার যুক্ত করে একটি বিশাল গতিপথ দিতে পারে! এখানে যে কভার একটি রেমন্ড Hettinger আলাপ করার জন্য একটি লিঙ্ক lru_cache। 26 মিনিট সম্পর্কে blip.tv/pycon-us-videos-2009-2010-2011/...
steveha

4
Lru_cache ব্যবহার করে, আপনি কাঁচা কোডের পরিবর্তে অন্য একটি অ্যালগরিদম ব্যবহার করেন। সুতরাং অভিনয়টি অ্যালগরিদম সম্পর্কে তবে ভাষাটি নয় but
ইস্টসুন

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

@ ইস্টসন ঠিক আছে, তবে অন্যদিকে অতিরিক্ত বাধা না দেওয়া পর্যন্ত উচ্চ স্তরের ভাষার সুবিধার অনুমতি দেওয়া উচিত। lru_cache গতির জন্য স্মৃতি ত্যাগ করবে এবং অ্যালগরিদমিক জটিলতা সামঞ্জস্য করবে।
ম্যাট জয়েনার

4
আপনি যদি অন্য অ্যালগরিদম ব্যবহার করেন তবে আপনি চালাবেন ইরোটোথিনিস চেষ্টা করতে। পাইথন সংস্করণ 100 কে আন্ডার 0.03সেকেন্ডে ( 30এমএস) এর জন্য একটি উত্তর তৈরি করেছিল
jfs

7

ফোর্টরানকে ভুলে যাবেন না! (বেশিরভাগ হাস্যকর, তবে আমি সি এর সাথে একই রকম পারফরম্যান্স আশা করব)। বিস্ময়বোধক পয়েন্ট সহ বিবৃতিগুলি alচ্ছিক, তবে ভাল শৈলী। ( !90 গ্লোবাল ইন একটি মন্তব্য চরিত্র)

logical function isprime(n)
IMPLICIT NONE !
integer :: n,i
do i=2,n
   if(mod(n,i).eq.0)) return .false.
enddo
return .true.
end

subroutine findprimes(m)
IMPLICIT NONE !
integer :: m,i
logical, external :: isprime

do i=11,m
   if(isprime(i) .and. isprime(i-6))then
      write(*,*) i-6,i
   endif
enddo
end

program main
findprimes(10*1000)
end

6

সি সংস্করণটির জন্য বেশ কয়েকটি সুস্পষ্ট অপ্টিমাইজেশনের কয়েকটি আমি প্রতিহত করতে পারিনি যা আমার মেশিনে এখন ১০০ কে পরীক্ষা করে ০.০ সেকেন্ড নিয়েছে (প্রশ্নে সি সংস্করণের চেয়ে ৫ গুণ দ্রুত, উভয়ই এমএসভিসি 2010 / অক্স নিয়ে সংকলিত) ।

int isprime( int x )
{
    int i, n;
    for( i = 3, n = x >> 1; i <= n; i += 2 )
        if( x % i == 0 )
            return 0;
    return 1;
}

void findprimes( int m )
{
    int i, s = 3; // s is bitmask of primes in last 3 odd numbers
    for( i = 11; i < m; i += 2, s >>= 1 ) {
        if( isprime( i ) ) {
            if( s & 1 )
                printf( "%d %d\n", i - 6, i );
            s |= 1 << 3;
        }
    }
}

main() {
    findprimes( 10 * 1000 );
}

এখানে জাভাতে অভিন্ন প্রয়োগ রয়েছে:

public class prime
{
    private static boolean isprime( final int x )
    {
        for( int i = 3, n = x >> 1; i <= n; i += 2 )
            if( x % i == 0 )
                return false;
        return true;
    }

    private static void findprimes( final int m )
    {
        int s = 3; // s is bitmask of primes in last 3 odd numbers
        for( int i = 11; i < m; i += 2, s >>= 1 ) {
            if( isprime( i ) ) {
                if( ( s & 1 ) != 0 )
                    print( i );
                s |= 1 << 3;
            }
        }
    }

    private static void print( int i )
    {
        System.out.println( ( i - 6 ) + " " + i );
    }

    public static void main( String[] args )
    {
        // findprimes( 300 * 1000 ); // for some JIT training
        long time = System.nanoTime();
        findprimes( 10 * 1000 );
        time = System.nanoTime() - time;
        System.err.println( "time: " + ( time / 10000 ) / 100.0 + "ms" );
    }
}

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

এই 100k রান জন্য আমার সময়:

  • 319ms সি / অক্স এবং সংকলন> NIL এর সাথে সংকলিত:
  • 312ms সি / অক্স এবং স্ট্যাটিক কাউন্টার সহ সংকলিত
  • > NIL এ আউটপুট সহ 324ms জাভা ক্লায়েন্ট ভিএম
  • স্ট্যাটিক কাউন্টার সহ 299ms জাভা ক্লায়েন্ট ভিএম

এবং 1 এম রান (16386 ফলাফল):

  • 24.95 ডিগ্রি সেন্টিগ্রেড / অক্স এবং স্ট্যাটিক কাউন্টার সহ সংকলিত
  • 25.08s স্থির কাউন্টার সহ জাভা ক্লায়েন্ট ভিএম
  • 24.86s স্থির কাউন্টার সহ জাভা সার্ভার ভিএম

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

এটি স্কালাকে বরং দ্রুত বলে মনে হচ্ছে কেন এমন একটি ইঙ্গিত দেয়। এটি জাভা ভিএম-তে চালিত হয় এবং এর ফলে এটি তার চিত্তাকর্ষক অভিনয় থেকে উপকৃত হয়।


4
প্রাইম চেক ফাংশনের জন্য x >> 1 এর পরিবর্তে স্কয়ার্ট (এক্স) এ যাওয়া আরও দ্রুত।
ইভ ফ্রিম্যান 19

4

স্কালায় তালিকার পরিবর্তে Tuple2 ব্যবহার করার চেষ্টা করুন, এটি আরও দ্রুত হওয়া উচিত। (X, y) টিপল 2 হওয়ায় কেবল 'তালিকা' শব্দটি সরিয়ে ফেলুন।

Tuple2 ইন্টার, লং এবং ডাবল এর জন্য বিশেষীকরণ করা হয়েছে যার অর্থ এটি raw কাঁচা ডেটাটাইপগুলি বাক্স / আনবক্স করতে হবে না। Tuple2 উত্স । তালিকাটি বিশেষায়িত নয়। তালিকা উত্স


তাহলে আপনি forallএটি কল করতে পারবেন না । আমি আরও ভেবেছিলাম যে এটি সবচেয়ে কার্যকর কোড নাও হতে পারে (আরও বেশি কারণ nকেবল একটি ভিউ ব্যবহারের পরিবর্তে বৃহত্তর জন্য একটি বড় কঠোর সংগ্রহ তৈরি করা হয় ) তবে এটি অবশ্যই সংক্ষিপ্ত + মার্জিত এবং আমি অবাক হয়ে গিয়েছিলাম যে এটি ব্যবহার করেও এটি কতটা ভাল সম্পাদন করেছে কার্যকরী শৈলী অনেক।
0__

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

4
এটি প্রকৃতপক্ষে দ্রুততর, def sexyPrimes(n: Int) = (11 to n).map(i => (i-6, i)).filter({ case (i, j) => isPrime(i) && isPrime(j) })এখানে এটি প্রায় 60% দ্রুত, সুতরাং সি কোডটি বীট করা উচিত :)
0__

হুম, আমি কেবল 4 বা 5% এর পারফরম্যান্স বৃদ্ধি পেয়েছি
পেয়েছি

4
আমি collectযথেষ্ট ধীর পাই । যদি আপনি প্রথমে ফিল্টারটি করেন এবং তারপরে মানচিত্রটি দ্রুত হয়। withFilterকিছুটা দ্রুত কারণ এটি আসলে মধ্যবর্তী সংগ্রহ তৈরি করে না। (11 to n) withFilter (i => isPrime(i - 6) && isPrime(i)) map (i => (i - 6, i))
লুইজি প্লিঞ্জ

4

গো (Golang.org) সংস্করণের কোড এখানে রয়েছে:

package main

import (
    "fmt"
)


func main(){
    findprimes(10*1000)
}

func isprime(x int) bool {
    for i := 2; i < x; i++ {
        if x%i == 0 {
            return false
        }
    }
    return true
}

func findprimes(m int){
    for i := 11; i < m; i++ {
        if isprime(i) && isprime(i-6) {
            fmt.Printf("%d %d\n", i-6, i)
        }
    }
}

এটি সি সংস্করণের মতোই দ্রুত চলেছিল।

একটি আসুস u81a ইন্টেল কোর 2 ডুও T6500 2.1GHz, 2MB এল 2 ক্যাশে, 800MHz এফএসবি ব্যবহার করছে Using 4 জিবি র‌্যাম

100k সংস্করণ: C: 2.723s Go: 2.743s

1000000 (100 কে এর পরিবর্তে 1 এম) সহ: C: 3m35.458s Go: 3m36.259s

তবে আমি মনে করি যে গো এর বিল্ট মাল্টিথ্রেডিং ক্ষমতাতে ব্যবহার করা এবং সেই সংস্করণটিকে নিয়মিত সি সংস্করণের সাথে (মাল্টিথ্রেডিং ছাড়াই) তুলনা করা ঠিক হবে, কারণ গোয়ের সাথে মাল্টিথ্রেডিং করা প্রায় খুব সহজ।

আপডেট: গোতে গোরআটাইনগুলি ব্যবহার করে আমি একটি সমান্তরাল সংস্করণ করেছি:

package main

import (
  "fmt"
  "runtime"
)

func main(){
    runtime.GOMAXPROCS(4)
    printer := make(chan string)
    printer2 := make(chan string)
    printer3 := make(chan string)
    printer4 := make(chan string)
    finished := make(chan int)

    var buffer, buffer2, buffer3 string

    running := 4
    go findprimes(11, 30000, printer, finished)
    go findprimes(30001, 60000, printer2, finished)
    go findprimes(60001, 85000, printer3, finished)
    go findprimes(85001, 100000, printer4, finished)

    for {
      select {
        case i := <-printer:
          // batch of sexy primes received from printer channel 1, print them
          fmt.Printf(i)
        case i := <-printer2:
          // sexy prime list received from channel, store it
          buffer = i
        case i := <-printer3:
          // sexy prime list received from channel, store it
          buffer2 = i
        case i := <-printer4:
          // sexy prime list received from channel, store it
          buffer3 = i
        case <-finished:
          running--
          if running == 0 {
              // all goroutines ended
              // dump buffer to stdout
              fmt.Printf(buffer)
              fmt.Printf(buffer2)
              fmt.Printf(buffer3)
              return
          }
      }
    }
}

func isprime(x int) bool {
    for i := 2; i < x; i++ {
        if x%i == 0 {
            return false
        }
    }
    return true
}

func findprimes(from int, to int, printer chan string, finished chan int){
    str := ""
    for i := from; i <= to; i++ {
        if isprime(i) && isprime(i-6) {
            str = str + fmt.Sprintf("%d %d\n", i-6, i)
      }
    }
    printer <- str
    //fmt.Printf("Finished %d to %d\n", from, to)
    finished <- 1
}

নিয়মিত সংস্করণ ব্যবহৃত ঠিক একই সময়ে গড় ২.74৪৩ সেকেন্ডে সমান্তরাল সংস্করণ ব্যবহৃত হয় the

সমান্তরাল সংস্করণ 1.706 সেকেন্ডে সমাপ্ত হয়েছে। এটি 1.5 মেগাবাইটেরও কম র‌্যাম ব্যবহার করেছে।

একটি বিজোড় বিষয়: আমার দ্বৈত কোর কুবুন্টু 64 বিট উভয় কোরে কখনও উঁকি দেয়নি। দেখে মনে হচ্ছে গো কেবল একটি কোর ব্যবহার করছে। একটি কল সঙ্গে স্থিরruntime.GOMAXPROCS(4)

আপডেট: আমি 1 এম সংখ্যা পর্যন্ত প্যারালাইলেজড সংস্করণটি চালিয়েছি। আমার সিপিইউ কোরগুলির মধ্যে একটি সর্বদা 100% ছিল, অন্যটি মোটেই ব্যবহৃত হয়নি (বিজোড়)। এটি সি এবং নিয়মিত গো সংস্করণের চেয়ে পুরো মিনিট বেশি সময় নিয়েছিল। :(

1000000 (100 কে এর পরিবর্তে 1 এম) সহ:

C: 3m35.458s Go: 3m36.259s Go using goroutines:3 মি 27.137 এস2m16.125s

100k সংস্করণ:

C: 2.723s Go: 2.743s Go using goroutines: 1.706s


আপনি কতটি বিটিডব্লু ব্যবহার করেছেন?
সর্বনাম-মনোনীত

4
আমার একটি আসুস u81a ইন্টেল কোর 2 ডুও টি 6500 2.1GHz, 2 এমবি এল 2 ক্যাশে, 800 মেগাহার্টজ এফএসবি রয়েছে। 4 জিবি র‌্যাম
সেবাস্তিয়ান গ্রিগনোলি

আপনি কী অপ্টিমাইজেশান সক্ষম সহ সি সংস্করণটি আসলে সংকলন করেছেন? ডিফল্ট গো সংকলক ইনলাইন করে না এবং সাধারণত এই ধরণের তুলনায় অনুকূলিত সি এর বিপরীতে একটি দুর্দান্ত পারফরম্যান্সের শিকার হয়। যোগ করুন -O3বা আরও ভাল।
ম্যাট জয়েনার

আমি কেবল আগেই করিনি, এবং 100 কে সংস্করণ -৩3 এর সাথে বা ছাড়াই একই পরিমাণ সময় নিয়েছিল
সেবাস্তিয়ান গ্রিগনোলি

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

4

এটির মজাদার জন্য, এখানে একটি সমান্তরাল রুবি সংস্করণ।

require 'benchmark'

num = ARGV[0].to_i

def is_prime?(n)
  (2...n).all?{|m| n%m != 0 }
end

def sexy_primes_default(x)
    (9..x).map do |i|
        [i-6, i]
    end.select do |j|
        j.all?{|j| is_prime? j}
    end
end

def sexy_primes_threads(x)
    partition = (9..x).map do |i|
        [i-6, i]
    end.group_by do |x|
        x[0].to_s[-1]
    end
    threads = Array.new
    partition.each_key do |k|
       threads << Thread.new do
            partition[k].select do |j|
                j.all?{|j| is_prime? j}
            end
        end
    end
    threads.each {|t| t.join}
    threads.map{|t| t.value}.reject{|x| x.empty?}
end

puts "Running up to num #{num}"

Benchmark.bm(10) do |x|
    x.report("default") {a = sexy_primes_default(num)}
    x.report("threads") {a = sexy_primes_threads(num)}
end

আমার 1.8GHz কোর আই 5 ম্যাকবুক এয়ারে, সম্পাদনার ফলাফলগুলি:

# Ruby 1.9.3
$ ./sexyprimes.rb 100000
Running up to num 100000
                 user     system      total        real
default     68.840000   0.060000  68.900000 ( 68.922703)
threads     71.730000   0.090000  71.820000 ( 71.847346)

# JRuby 1.6.7.2 on JVM 1.7.0_05
$ jruby --1.9 --server sexyprimes.rb 100000
Running up to num 100000
                user     system      total        real
default    56.709000   0.000000  56.709000 ( 56.708000)
threads    36.396000   0.000000  36.396000 ( 36.396000)

# JRuby 1.7.0.preview1 on JVM 1.7.0_05
$ jruby --server sexyprimes.rb 100000
Running up to num 100000
             user     system      total        real
default     52.640000   0.270000  52.910000 ( 51.393000)
threads    105.700000   0.290000 105.990000 ( 30.298000)

দেখে মনে হচ্ছে যে জেভিএমের জেআইটি ডিফল্ট ক্ষেত্রে রুবিকে একটি দুর্দান্ত পারফরম্যান্স বাড়া দিচ্ছে, যখন সত্যিকারের মাল্টিথ্রেডিং জেআরবিকে থ্রেডেড মামলায় 50% দ্রুত সম্পাদন করতে সহায়তা করে। আরও মজার বিষয় হ'ল জেআরবি ১.7 স্বাস্থ্যকর 17% দ্বারা জেআরবি 1.6 স্কোরকে উন্নত করে!


3

X4u এর উত্তরের ভিত্তিতে , আমি পুনরাবৃত্তি ব্যবহার করে একটি স্কালা সংস্করণ লিখেছিলাম এবং প্রাইম চেক ফাংশনের জন্য আমি এক্স / 2 এর পরিবর্তে স্কয়ার্টে গিয়ে উন্নত করেছি। আমি 100 কে জন্য 250 মিলিয়ন ডলার এবং 1 এম এর জন্য 600 ডলার পাই। আমি এগিয়ে গিয়েছিলাম এবং 6 এমএসে 10 এম গিয়েছিলাম।

import scala.annotation.tailrec

var count = 0;
def print(i:Int) = {
  println((i - 6) + " " + i)
  count += 1
}

@tailrec def isPrime(n:Int, i:Int = 3):Boolean = {
  if(n % i == 0) return false;
  else if(i * i > n) return true;
  else isPrime(n = n, i = i + 2)
}      

@tailrec def findPrimes(max:Int, bitMask:Int = 3, i:Int = 11):Unit = {
  if (isPrime(i)) {
    if((bitMask & 1) != 0) print(i)
    if(i + 2 < max) findPrimes(max = max, bitMask = (bitMask | (1 << 3)) >> 1, i = i + 2)
  } else if(i + 2 < max) {
    findPrimes(max = max, bitMask = bitMask >> 1, i = i + 2)
  }
}

val a = System.currentTimeMillis()
findPrimes(max=10000000)
println(count)
val b = System.currentTimeMillis()
println((b - a).toString + " mils")

আমি ফিরে গিয়ে একটি কফি স্ক্রিপ্ট (ভি 8 জাভাস্ক্রিপ্ট) সংস্করণও লিখেছিলাম, যা একটি কাউন্টার ব্যবহার করে (I / O উপেক্ষা করে) 100 কে, 15 এমএসের জন্য 250 মিমি এবং 10 এম এর জন্য 6 এস পায় gets যদি আমি আউটপুট চালু করি তবে এটি 100 কে জন্য 150 ডলার, 1 এম এর জন্য 1 এস, এবং 10 এম এর জন্য 12 এস লাগবে। দুর্ভাগ্যক্রমে এখানে লেজ পুনরাবৃত্তি ব্যবহার করতে পারিনি, তাই আমাকে এটিকে আবার লুপে রূপান্তর করতে হয়েছিল।

count = 0;
print = (i) ->
  console.log("#{i - 6} #{i}")
  count += 1
  return

isPrime = (n) ->
  i = 3
  while i * i < n
    if n % i == 0
      return false
    i += 2
  return true

findPrimes = (max) ->
  bitMask = 3
  for i in [11..max] by 2
    prime = isPrime(i)
    if prime
      if (bitMask & 1) != 0
        print(i)
      bitMask |= (1 << 3)
    bitMask >>= 1
  return

a = new Date()
findPrimes(1000000)
console.log(count)
b = new Date()
console.log((b - a) + " ms")

2

আপনার # 1 প্রশ্নের উত্তর হ্যাঁ, জেভিএম অবিশ্বাস্যভাবে দ্রুত এবং হ্যাঁ স্ট্যাটিক টাইপিংয়ে সহায়তা করে।

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

জাভার গতির কারণগুলি:

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

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

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

জেভিএম আপনার সিপিইউ আর্কিটেকচার সম্পর্কে শিখতে পারে এবং নির্দিষ্টভাবে প্রদত্ত সিপিইউয়ের জন্য বিশেষত মেশিন কোড উত্পন্ন করতে পারে।

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

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


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

4
@ ড্যানিয়েলসি.সোব্রাল ভাষা ইমেলমেন্টেশন হিসাবে তেমন গুরুত্বপূর্ণ নয় - জাভার "হিপ" বাস্তবায়ন কোড সি এর মতো কিছু নয়। জাভা হ'ল একটি পুনঃনিরীক্ষণযোগ্য বহু-পর্যায়ের সিস্টেম যা বিভিন্ন লক্ষ্যগুলির জন্য অত্যন্ত অপটিমাইজযোগ্য যা আজকের দিনে আধুনিক প্রযুক্তি উদ্ভাবন সহ গবেষণায় বহু-বছর চেষ্টা করে, সি একটি গাদা ব্যবহার করে - যুগ যুগ আগে বিকশিত একটি সাধারণ তথ্য কাঠামো। জা এর সিস্টেম সি এর জন্য বাস্তবায়ন করা অসম্ভব যে সি পয়েন্টারগুলিকে অনুমতি দেয় যাতে এটি ভাষা পরিবর্তন ছাড়াই নির্বিচারে বরাদ্দকৃত মেমরি খণ্ডগুলির "নিরাপদ" পদক্ষেপের গ্যারান্টি দিতে পারে না (এটিকে আর সি না করে)
বিল কে

নিরাপদতা অপ্রাসঙ্গিক - আপনি এটি নিরাপদ বলে দাবি করেননি , আপনি দাবি করেছেন যে এটি আরও দক্ষ । তদ্ব্যতীত, সি "হিপ" কীভাবে কাজ করে তার মন্তব্যে আপনি বর্ণনা করেছেন যে বাস্তবে কোনও ফল নেই।
ড্যানিয়েল সি সোব্রাল

আপনার অবশ্যই আমার "নিরাপদ" অর্থটি ভুল বুঝে থাকতে হবে - জাভা যে কোনও সময় স্মৃতিচারণের স্বেচ্ছাসেবী ব্লকটি স্থানান্তর করতে সক্ষম হয় কারণ এটি জানে এটি সি, মেমরি বরাদ্দকে অপ্টমাইজ করতে সক্ষম হয় না কারণ এমন পয়েন্টার থাকতে পারে যা এটি উল্লেখ করতে পারে। এছাড়াও এসি হিপ সাধারণত একটি হিপ হিসাবে প্রয়োগ করা হয় যা একটি ডেটা স্ট্রাকচার। সি ++ হিপগুলি সি এর মতো হিপ স্ট্রাকচারের সাথে প্রয়োগ করা হত (অতএব নাম, "হিপ") আমি কয়েক বছরের জন্য সি ++ এ পরীক্ষা করে দেখিনি যাতে এটি আর সত্য হয় না তবে এটি এখনও সক্ষম না হয়ে সীমাবদ্ধ ইচ্ছায় ব্যবহারকারীর বরাদ্দ মেমরির ছোট অংশগুলি পুনরায় ব্যবস্থা করুন।
বিল কে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.