Стоимость процессора на порядок для некоторых основных операций - PullRequest
2 голосов
/ 12 февраля 2011

После ответа на на этот ТАК вопрос и на то, что я не голосую, я хотел бы кое-что с вами проверить.

Чтобы получить предварительное представление о стоимости написанного мной кода,У меня есть тенденция масштабировать операции таким образом.

  • Распределение кучи примерно в 1000 раз медленнее, чем распределение стеков.
  • IO с экраном / выводом примерно в 1000 раз медленнее, чем распределение кучи.
  • IO на жестком диске примерно в 1000 раз медленнее, чем графический ввод на экране.

Считаете ли вы, что это правильное предположение / порядок величины / оценки?

(И, конечно же, нет ничего лучше, чем реальное профилирование приложения: -))

РЕДАКТИРОВАТЬ: в качестве первого вывода в соответствии с вашими ответами и комментариями, можно сказать, что моя цифра 1000 в значительной степени 1020 * завышен.

Ответы [ 3 ]

5 голосов
/ 12 февраля 2011

Если вы собираетесь сделать такие обширные обобщения, вы можете подумать о том, чтобы иметь надежные данные для их резервного копирования.

Я не сомневаюсь, что вы правы относительно относительной эффективности большинство архитектур (я говорю наиболее просто, потому что там могут быть какие-то странные архитектуры, о которых я не знаю), но отношения 1000x подозрительны без доказательств.

И на самом деле,Я не уверен, что уверен в относительной эффективности экранного и дискового ввода-вывода, поскольку на него может повлиять буферизация.Я часто обнаруживал, что программа, выводящая тысячи строк на экран, работает быстрее при направлении вывода в файл на диске.

Например, следующая программа:

#include <stdio.h>
int main (void) {
    int i;
    for (i = 100000; i > 0; i--)
        printf ("hello\n");
    return 0;
}

запускается как:

pax$ time myprog
hello
hello
:
hello

real    0m12.861s
user    0m1.762s
sys     0m2.002s

pax$ time ./myprog >/tmp/qq

real    0m0.191s
user    0m0.160s
sys     0m0.050s

Другими словами, экранный ввод-вывод в этой среде (CygWin под XP) занимает в 67 раз больше времени и в 17 раз больше времени процессора (предположительно из-за всех обновлений Windows).

3 голосов
/ 12 февраля 2011

Вот еще один быстрый и интересный, если не научно надежный и недостаточно продуманный тест:

char *memory;
NSLog (@"Start heap allocs");
for (int allocations = 0;  allocations < 100000000;  allocations++)
{
    memory = malloc (1024);
    memory[0] = 1;
    memory[1023] = memory[0] + 1;
    free(memory);
}
NSLog (@"End heap allocs");
NSLog (@"Start stack allocs");
for (int allocations = 0;  allocations < 100000000;  allocations++)
{
    char memory2 [1024];
    memory2[0] = 1;
    memory2[1023] = memory2[0] + 1;
}
NSLog (@"End stack allocs");

и вывод:

2011-02-12 11:46:54.078 Veg Met Chilli[4589:207] Start heap allocs
2011-02-12 11:47:06.759 Veg Met Chilli[4589:207] End heap allocs
2011-02-12 11:47:06.759 Veg Met Chilli[4589:207] Start stack allocs
2011-02-12 11:47:07.057 Veg Met Chilli[4589:207] End stack allocs

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

РЕДАКТИРОВАТЬ: новые данные испытаний.

Так что теперь я просто вызываю метод для каждого выделения кучи и стека, а не помещаю их сразу в цикл. Результаты:

2011-02-12 12:13:42.644 Veg Met Chilli[4678:207] Start heap allocs
2011-02-12 12:13:56.518 Veg Met Chilli[4678:207] End heap allocs
2011-02-12 12:13:56.519 Veg Met Chilli[4678:207] Start stack allocs
2011-02-12 12:13:57.842 Veg Met Chilli[4678:207] End stack allocs

Это позволяет распределять кучи только в 10 раз больше, чем выделяет стек. Чтобы сделать результаты более точными, у меня также должен быть метод контроля, который не выделяет память (но, по крайней мере, делает что-то, чтобы не оптимизироваться), и отнимаю это время. Я сделаю это дальше ...

РЕДАКТИРОВАТЬ: Верно ... Теперь код выглядит так:

int control = 0;
NSLog (@"Start heap allocs");
for (int allocations = 0;  allocations < 100000000;  allocations++)
{
    control += [self HeapAlloc];
}
NSLog (@"End heap allocs");
NSLog (@"Start stack allocs");
for (int allocations = 0;  allocations < 100000000;  allocations++)
{
    control += [self StackAlloc];
}
NSLog (@"End stack allocs");
NSLog (@"Start no allocs");
for (int allocations = 0;  allocations < 100000000;  allocations++)
{
    control += [self NoAlloc];
}
NSLog (@"End no allocs");
NSLog (@"%d", control);


-(int) HeapAlloc
{
    int controlCalculation = rand();

    char *memory = malloc (1024);
    memory[0] = 1;
    memory[1023] = memory[0] + 1;
    free(memory);

    return controlCalculation;
}

-(int) StackAlloc
{
    int controlCalculation = rand();

    char memory [1024];
    memory[0] = 1;
    memory[1023] = memory[0] + 1;   

    return controlCalculation;
}

-(int) NoAlloc
{
    int controlCalculation = rand();

    return controlCalculation;
}

и результаты:

2011-02-12 12:31:32.676 Veg Met Chilli[4816:207] Start heap allocs
2011-02-12 12:31:47.306 Veg Met Chilli[4816:207] End heap allocs
2011-02-12 12:31:47.306 Veg Met Chilli[4816:207] Start stack allocs
2011-02-12 12:31:49.458 Veg Met Chilli[4816:207] End stack allocs
2011-02-12 12:31:49.459 Veg Met Chilli[4816:207] Start no allocs
2011-02-12 12:31:51.325 Veg Met Chilli[4816:207] End no allocs

Таким образом, контрольное время составляет 1,866 секунды. Уберите это из выделенного времени: стек 0,286 секунды куча 12,764 секунды

Таким образом, выделение кучи занимает в 45 раз больше времени, чем выделение стека.

Спасибо и спокойной ночи! :)

2 голосов
/ 12 февраля 2011

1-й пункт зависит от многих вещей, правда.Если вам не хватает памяти, то выделение чего-либо в куче может занять буквально минуты.С другой стороны, стек может быть уже выделен в этой точке.

2-ая точка зависит от используемого терминала.Вывод на экран DOS - это одно, вывод в консольное окно Windows - это совсем другое, и xterm тоже совершенно не похож на них.

Что касается третьего пункта, я бы сказал, что это наоборот.для современных жестких дисков.Они могут легко обрабатывать мегабайты в секунду, как вы можете представить, что выводит столько на любой терминал за такое короткое время?Однако для небольших объемов данных вы можете быть правы, поскольку для ввода-вывода с жесткого диска может потребоваться некоторое время для подготовки.

...