C # Оптимизация памяти для больших массивов - PullRequest
4 голосов
/ 22 мая 2011

Вот две части кода в c ++ и c #, которые делают абсолютно одно и то же:

C ++
http://ideone.com/UfL5R

#include <stdio.h>
int main(int argc, char *argv[]) {
  char p[1000000];
  unsigned int i,j;
  unsigned long long s=0;
  for(i=2;i<1000000;i++) p[i]=1;
  for(i=2;i<500000;) {
    for(j=2*i;j<1000000;j+=i) p[j]=0;
    for(i++;!p[i];i++);
  }
  for(i=3,s=2;i<1000000;i+=2) if(p[i]) s+=i;
  printf ("%lld\n",s);
  return 0;
}

время: 0,01 с, память: 2576 кБ

C #
http://ideone.com/baXYm

using System;

namespace ConsoleApplication4
{
    internal class Program
    {
        private  static void Main(string[] args)
        {
            var p = new byte[1000000];
            ulong i, j;
            double s = 0;
            for(i=2;i<1000000;i++) 
                p[i]=1;

            for(i=2;i<500000;) 
            {
                for(j=2*i;j<1000000;j+=i) 
                    p[j]=0;
                for(i++;p[i]==0;i++);
            }

            for(i=3,s=2;i<1000000;i+=2) 
                if(p[i]!=0) s+=i;

            Console.WriteLine(s);
        }
    }
}

время: 0,05 с памяти: 38288 кБ

Как я могу улучшить код C #, чтобы доказать, что C # может быть таким же быстрым, как C ++, моему коллеге?

Как видите, время выполнения C # в 5 раз больше, а потребление памяти - в 15 раз.

Ответы [ 5 ]

9 голосов
/ 22 мая 2011

Скомпилируйте и запустите в режиме Release.Я получаю ровно 0,01 с версии C # при сборке и запуске в режиме выпуска.Что касается потребления памяти, вы сравниваете яблоки с апельсинами.Управляемая среда будет потреблять больше памяти, так как она содержит CLR и сборщик мусора, которые не предоставляются бесплатно.

6 голосов
/ 22 мая 2011

Как я могу улучшить код C #, чтобы доказать, что C # может быть таким же быстрым, как C ++, моему коллеге?

Ты не можешь. Есть законные области, где C ++ существенно быстрее, чем C #. Но есть также области, где код C # будет работать лучше, чем эквивалентный код C ++. Это разные языки с разными сильными и слабыми сторонами.

Но, как программист, вы действительно должны основывать свои решения на логике.

Логика требует, чтобы вы сначала собрали информацию, а затем решили на ее основе.

Вы, наоборот, сначала приняли решение , а затем искали информацию для его поддержки. Это может сработать, если вы политик, но это не очень хороший способ писать программы.

Не ищите доказательств того, что C # быстрее C ++. Вместо этого, проверьте, какой вариант быстрее в вашем случае .

В любом случае, если вы хотите доказать, что X может работать так же быстро, как Y, вы должны сделать это обычным способом: сделать X так же быстро, как Y. И, как всегда, при настройке производительности профилировщик - это ваш лучший друг. Узнайте, где именно проводится дополнительное время, а затем выясните, как его устранить.

Однако использование памяти потеряно. .NET просто использует больше памяти по нескольким причинам:

  • имеет большую библиотеку времени выполнения, которая должна присутствовать в адресном пространстве процесса
  • .NET-объекты имеют дополнительные члены, которых нет в классах C ++, поэтому они используют больше памяти
  • сборщик мусора означает, что у вас обычно будет некоторое количество памяти «больше не используется, но еще не утилизирован». В C ++ память обычно освобождается немедленно. В .NET это не так. .NET основан на предположении, что память дешева (что обычно так)
4 голосов
/ 22 мая 2011

Как значительно повысить производительность вашего кода C #

Идите «небезопасно» (неуправляемо) для этого ... каждый раз, когда вы делаете someSortOfArray[i], .NET Framework делает все виды аккуратных вещей (таких как проверка вне границ), которые занимают время .

В этом и заключается весь смысл неуправляемости (а затем использования указателей и выполнения myPointer ++).

Просто чтобы уточнить, что если вы неуправляемы, а затем продолжаете делать for-loop и делаете someArray[i], вы ничего не сохранили.

Другой С.О. вопрос, который может вам помочь: True Unsafe Code Performance

Отказ

Кстати, я говорю не о том, чтобы делать это все время, а скорее как ответ только на ЭТОТ конкретный вопрос.

3 голосов
/ 23 февраля 2012

Просто примечание к вашему времени. Не показано, как вы измерили время выполнения. Можно ожидать разумных накладных расходов для приложений .NET при запуске. Так что, если вам нужно время выполнения только циклов, вы должны запускать внутренние циклы несколько (много) раз, пропустить первые итерации 1..2, измерить другие итерации и вычислить среднее значение.

Я ожидаю, что результаты будут более похожими, чем. Однако, как всегда при нацеливании на «пиковую производительность» - важны меры предосторожности в отношении управления памятью. Здесь, вероятно, было бы достаточно предотвратить «новое» внутри измерительных функций. Повторно используйте p [] в каждой итерации.

1 голос
/ 22 мая 2011

Использование памяти может быть связано с сборкой мусора. В Java использование памяти преднамеренно высоко - сборка мусора происходит только тогда, когда вам нужно больше памяти. Это из соображений скорости, поэтому было бы разумно, чтобы C # делал то же самое. Вы не должны делать это в коде выпуска, но чтобы показать большой объем памяти, который вы фактически используете, вы можете позвонить GC.Collect() перед измерением использования памяти. Вы действительно заботитесь, сколько памяти это использует все же? Кажется, скорость важнее. И если у вас есть ограничения памяти, вы можете установить объем памяти, который ваша программа будет использовать перед сборкой мусора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...