shootout, cs2n, nsieve и прочее
От: cl-user  
Дата: 26.02.07 10:38
Оценка:
Залез на shootout — решил сравнить C# и N. Содрал тесты для C#, перегнал их cs2n, стал смотреть и мерять. Вот из этого

using System;

class NSieve
{
   static int nsieve(int m, bool[] isPrime) {
      for (int i=2; i <= m; i++) isPrime[i] = true;
      int count = 0;

      for (int i=2; i <= m; i++){
         if (isPrime[i]){
            for (int k=i+i; k <= m; k+=i) isPrime[k] = false;
            count++;
         }
      }
      return count;
   }

   public static void Main(String[] args)
   {
      int n = 2;
      if (args.Length > 0) n = Int32.Parse(args[0]);
      if (n < 2) n = 2;

      int m = (1<<n)*10000;
      bool[] flags = new bool[m+1];
      Console.WriteLine("Primes up to {0,8:D} {1,8:D}", m, nsieve(m,flags));

      m = (1<<n-1)*10000;
      Console.WriteLine("Primes up to {0,8:D} {1,8:D}", m, nsieve(m,flags));

      m = (1<<n-2)*10000;
      Console.WriteLine("Primes up to {0,8:D} {1,8:D}", m, nsieve(m,flags));
   }
}


получилось вот это

using System;

class NSieve
{
   static nsieve(m : int, isPrime : array [bool]) : int {
      for (mutable  i=2; i <= m; i++) isPrime[i] = true;
      mutable count = 0;

      for (mutable  i=2; i <= m; i++){
         when (isPrime[i]){
            for (mutable  k=i+i; k <= m; k+=i) isPrime[k] = false;
            count++;
         }
      }
       count;
   }

   public static Main(args : array [String]) :  void
   {
      mutable  n = 2;
      when (args.Length > 0) n = Int32.Parse(args[0]);
      when (n < 2) n = 2;

      mutable m = (1<<n)*10000;
      def flags = array(m+1);
      Console.WriteLine("Primes up to {0,8:D} {1,8:D}", m, nsieve(m,flags));

      m = (1<<n-1)*10000;
      Console.WriteLine("Primes up to {0,8:D} {1,8:D}", m, nsieve(m,flags));

      m = (1<<n-2)*10000;
      Console.WriteLine("Primes up to {0,8:D} {1,8:D}", m, nsieve(m,flags));
   }
}


(а для N ещё нет оформления кода? )

Различие в скорости получилось мизерным: для аргумента 12 при общем времени выполнения теста ~8 сек. разница составила в среднем 0.03 — 0.05 с. на моей машине в пользу C#.

Интересует — как не меняя сути алгоритма переписать тест для большей выразительности/лаконичности кода? Может и в скорости чуть подтянемся?

P.S. Portable.NET "продул" моно почти в полтора раза — > 11 сек. против 8. NET-а от M$ нет — сравнить не могу

P.P.S. Хм, если снести массив внутрь функции и переписать логику с учётом инициализации в N массива по умолчанию:

using System;

class NSieve
{
   static nsieve(mutable m : int) : int {
      def isPrime = array(m+1) : array [bool];
      mutable count = 0;

      for (mutable  i=2; i <= m; i++){
         unless (isPrime[i]){
            for (mutable  k=i+i; k <= m; k+=i) isPrime[k] = true;
            count++;
         }
      }
       count;
   }

   public static Main(mutable args : array [String]) :  void
   {
      mutable  n = 2;
      when (args.Length > 0) n = Int32.Parse(args[0]);
      when (n < 2) n = 2;

      mutable m = (1<<n)*10000;
      Console.WriteLine("Primes up to {0,8:D} {1,8:D}", m, nsieve(m));

      m = (1<<n-1)*10000;
      Console.WriteLine("Primes up to {0,8:D} {1,8:D}", m, nsieve(m));

      m = (1<<n-2)*10000;
      Console.WriteLine("Primes up to {0,8:D} {1,8:D}", m, nsieve(m));
   }
}


уже получим выигрыш N, но опять совсем незначительный — ~0.2 с (три прохода по массиву?)

P.P.P.S. Просьба не ругаться за то, что маюсь разной х..нёй

P.P.P.P.S. С аргументом 14 выигрыш N составил ~0,8 с, но это всё в пределах погрешности, ибо на двух десятках итераций разница между максимальным и минимальным временем более 10%
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.