Каким должен быть язык программирования? Анализ и критика Описание языка Компилятор
Отечественные разработки Cтатьи на компьютерные темы Компьютерный юмор Новости и прочее

C vs Haskell: сравнение скорости на простом примере

Ранее мы сравнивали одни программы на Си с другими программами на Си, которые отличаются от первых характерными для Хаскелла приёмами. А теперь сравним программу на Си и программу на Хаскелле. Выберем простейшую задачу прочитать содержимое файла и просуммировать 32-битных слов в нём.

Ниже — программа, решающая её на Хаскелле. Насколько правильно, насколько эффективно — судить не берусь. Но раз не побоялись выложить код на всеобщее обозрение, значит он приемлем для программистов на Хаскелле.

import System.Environment
import Data.Binary
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy.Internal as L
import System.IO
import qualified Data.ByteString.Lazy as L
import Data.Binary.Get
import Data.Word
 
main::IO()
main = do
  args <- getArgs
  a <- (calculateSumInFile (head args))
  print a
 
calculateSumInFile:: FilePath->IO Word32
calculateSumInFile path =
    withBinaryFile path ReadMode $ \h ->
        let byWords s = do
                w <- L.hGet h 4
                if L.length w == 4 then
                    byWords $ s + runGet getWord32host w
                else return s
        in byWords 0

А теперь решение той же задачки на Си. Опущу неинтересное, чтобы не утомлять читателя лишними подробностями. Вот главное в коде:

. . .
fread(буфер, длина, 1, файл откуда);
. . .
_31  x = 0;
_31  i = 0;
_31*  очередное слово = (_31*) буфер;
for (; i < длина; i += 4, ++очередное слово)
	x += *очередное слово;
printf( "Результат: %d\n", x); 

Забегая вперёд, скажу, что обе программки выдают одинаковый результат — ту сумму, которую надо вывести в консоль. Это с большой вероятностью говорит, что оба примера правильно решают исходную задачу.

Для тестирования использовались те же компьютеры, что и в предыдущих тестах. А вот размер файла менялся от 1Мб до 256 Мб. Опять замер проводился на компьютерах A, B и C, для каждого из них измерялось время прохождения теста на Си (первая колонка), Хаскелл (вторая) и соотношение времени, затраченное программой на Хаскелл ко времени, затраченном программой на Си. Вот полученные результаты:

  A B C
Размер  C Haskell Соотн. C Haskell Соотн. C Haskell Соотн.
1 Мб 0,104 1,473 14,16 0,047 1,05 22,34 0,016 0,438 27,38
4 Мб 0,172 3,871 22,51 0,078 2,69 34,49 0,062 1,016 16,39
16 Мб 0,25 15,23 60,94 0,109 9,619 88,25 0,078 3,938 50,49
64 Мб 0,422 79,24 187,8 0,202 44,88 222,2 0,125 16,64 133,1
256 Мб 6,812 7645 1122 0,639 1070 1674 2,672 4017 1503

Вынесем соотношения в отдельную табличку:

  A B C
1 Мб 14,16 22,34 27,38
4 Мб 22,51 34,49 16,39
16 Мб 60,94 88,25 50,49
64 Мб 187,8 222,2 133,1
256 Мб 1122 1674 1503

И построим график:

C vs Haskell: сравнение скорости на простом примере

С увеличением размера файла соотношение времен исполнения на Хаскелл и Си взмывает по экспоненте. Преобразуем результаты предыдущей таблицы, применив к ним функцию двоичного логарифма:

  A B C
1 Мб 3,824 4,4816 3,895
4 Мб 4,492 5,108 4,034
16 Мб 5,929 6,4635 5,658
64 Мб 7,553 7,7957 7,057
256 Мб 10,13 10,709 10,55

В логарифмическом масштабе график более нагляден:

C vs Haskell: сравнение скорости на простом примере

Выводы

Если размер файла небольшой (1 Мб), то разница между программками на Хаскелле и Си — в разы. С возрастанием размера файла разница становится чудовищной, в несколько порядков. Так что программирование на Хаскелл требует внимательности и аккуратности, не все его средства одинаково полезны.

Ещё одно любопытное наблюдение: компилятор Tiny CC для программки на Си подготовил исполняемый файл размером 3584 байтов. А вот компилятор GHC «выдал на гора» 15Мб. Почувствуйте разницу. Оптимизировали, оптимизировали GHC, да так и не дооптимизировали.

Вывод Филипа Уодлера, одного из соавторов Хаскелла, о двухкратной разнице по скорости Си и Хаскелла, легко опровергается простым примером. Это один из ответов на вопрос, почему Хаскелл так мало используется в отрасли.

Post Scriptum

Д.Ю.Караваев прислал мне программку, делающую то же самое, но на PL/1. Запустил программку на компьютере конфигурации A, получил следующие результаты (время исполнения в процентах от программы на Си):

  • 1 Мб — 98%
  • 4 Мб — 91%
  • 16 Мб — 94%
  • 64 Мб — 85%
  • 256 Мб — 86%
Объективности ради надо отметить, что время исполнения оказалось, как правило, меньше секунды. Следовательно, погрешность измерений имела место быть. Тем не менее, в целом отечественный компилятор PL/1 выглядит достойно на импортном фоне.

Post Post Scriptum

Нашёл задачку вычисления определителя квадратной матрицы на Хаскелле. Автор — Борис Файфель, кандидат физико-математических наук, доцент Института прикладных информационных технологий и коммуникаций в Саратове. Известен как разработчик HomeLisp.

Решил написать программку на Си, которая вычисляет то же самое, чтобы увидеть разницу в скорости работы массивов на Си и списков на Хаскелле. Чтобы была возможность сравнить, необходимо увеличить размерность матрицы. Для начала выбрал размер матрицы 512 на 512. Сгенерировал случайные числа в количестве 512 на 512. Но если компилятор TinyCC отработал благополучно, то с Хаскеллем возникли проблемы. Компилятор GHC выдал сообщение:

Попытка выделить более 129024 байт. В настоящее время это невозможно из-за ограничений генератора кода GHC. Предложение: читайте данные из файла вместо больших статических структур данных в коде.

Вот это да! На что ещё годен Хаскелл, кроме защиты диссертаций?! Десятки британских учёных защитили на нём учёные степени, а довести до ума компилятор — руки не дошли. А между тем, компилятор TinyCC написал одиночка и проблем с объёмом статических данных в нём не наблюдается.

Опустился до матрицы 128x128, тогда компиляция прошла успешно. Но после запуска программка выдала: «Infinity». На этом желание сравнивать иссякло.

Опубликовано: 2022.01.01, последняя правка: 2022.02.10    20:49

ОценитеОценки посетителей
   ████████████ 5 (27.7%)
   ███████ 3 (16.6%)
   ████████████ 5 (27.7%)
   ████████████ 5 (27.7%)

Отзывы

     2022/05/14 13:13, MihalNik          # 

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

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

кандидат физико-математических наук, доцент

Как будто кандидат наук не может писать программ уровня студента. Где толпы ленивых студентов на форумах, умоляющих решить им горящие до завтра задачки на Хаскелле? Нет их, а значит и преподавания Хаскелла по сути нет, как нет или почти нет грамотных специалистов, умеющих с ним работать.

А может некоторые наши студенты делают ЯП и получше некоторых британских ученых. Просто так может получиться, когда что-то делается для себя, из любопытсва, а не ради должностей и зарплат.

     2022/05/14 19:29, Автор сайта          # 

Или для галочки по требованию образовательного учреждения.

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

Где толпы ленивых студентов на форумах, умоляющих решить им горящие до завтра задачки на Хаскелле? Нет их, а значит и преподавания Хаскелла по сути нет, как нет или почти нет грамотных специалистов, умеющих с ним работать.

Ну в этом Вы правы. Об уровне соответствующих специалистов можно косвенно судить по уровню учебников. Они не ахти какие, значит их особо-то и некому писать.

     2022/05/15 08:55, MihalNik          # 

Ну что Вы. В этом трудно заподозрить человека

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

в целом отечественный компилятор PL/1 выглядит достойно на импортном фоне

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

     2022/05/15 14:50, Автор сайта          # 

Было бы очень здорово провести более глубокое сравнение с разными компиляторами языка C на разных машинах

Да, хорошая мысль. Неплохо бы разработать набор различных заданий, чтобы их реализовать на разных языках и компиляторах. Набор должен быть достаточно разнообразным, чтобы можно было давать оценки скорости работы как плавающей, так и фиксированной арифметики, строк и всего прочего. Подозреваю, что такой набор уже где-то существует, но чтоб его найти, нужна достаточная степень любопытства :)

Добавить свой отзыв

Написать автору можно на электронную почту
mail(аt)compiler.su

Авторизация

Регистрация

Выслать пароль

Карта сайта


Содержание

Каким должен быть язык программирования?

Анализ и критика

●  Устарел ли текст как форма представления программы

●  Русский язык и программирование

●  Многоязыковое программирование

Синтаксис языков программирования

Синтаксический сахар

●  Некоторые «вкусности» Алгол-68

●  «Двухмерный» синтаксис Python

●  Почему языки с синтаксисом Си популярнее языков с синтаксисом Паскаля?

●  Должна ли программа быть удобочитаемой?

●  Стиль языка программирования

●  Тексто-графическое представление программы

●●  Разделители

●●  Строки программы

●●  Слева направо или справа налево?

●  Комментарии

●●  Длинные комментарии

●●  Короткие комментарии

●●  Комментарии автоматической генерации документации

●●  Нерабочий код

●●  Помеченные комментарии

●  Нужны ли беззнаковые целые?

●  Шестнадцатиричные и двоичные константы

●  Условные операторы

●  Переключатель

●  Циклы

●●  Продолжение цикла и выход из него

●  Некошерный «goto»

●  Изменение приоритетов операций

●  Операции присвоения и проверки на равенство. Возможно ли одинаковое обозначение?

●  Так ли нужны операции «&&», «||» и «^^»?

●  Постфиксные инкремент и декремент

●  Почему в PHP для конкатенации строк используется «.»?

●  Указатели и ссылки в C++

●●  О неправомерном доступе к памяти через указатели

●  Обработка ошибок

●  Функциональное программирование

●●  Нечистые действия в чистых функциях

●●  О чистоте и нечистоте функций и языков

●●  Макросы — это чистые функции, исполняемые во время компиляции

●●  Хаскелл, детище британских учёных

●●  Измеряем замедление при вызове функций высших порядков

●●  C vs Haskell: сравнение скорости на простом примере

●●  Уникальность имён функций: за и против

●●  Каррирование: для чего и как

●●  О тестах, доказывающих отсутствие ошибок

●  Надёжные программы из ненадёжных компонентов

●●  О многократном резервировании функций

●  Использование памяти

●  Почему динамическое распределение памяти — это плохо

●  Как обеспечить возврат функциями объектов переменной длины?

●●  Типы переменного размера (dynamically sized types, DST) в языке Rust

●●  Массивы переменной длины в C/C++

●●  Размещение объектов в стеке, традиционный подход

●●  Размещение объектов переменной длины с использованием множества стеков

●●  Размещение объектов переменной длины с использованием двух стеков

●●  Реализация двухстековой модели размещения данных

●●  Двухстековая модель: тесты на скорость

●●  Изменение длины объекта в стеке во время исполнения

●●  Размещение объектов переменной длины с использованием одного стека

●  Можно ли забыть о «куче», если объекты переменной длины хранить в стеке

●  Безопасность и размещение объектов переменной длины в стеке

●  Массивы, структуры, типы, классы переменной длины

●  О хранении данных в стеке, вместо заключения

●  Реализация параметрического полиморфизма

Описание языка

Компилятор

Отечественные разработки

Cтатьи на компьютерные темы

Компьютерный юмор

Новости и прочее




Последние отзывы

2024/04/25 21:05 ••• Ttimofeyka
Энтузиасты-разработчики компиляторов и их проекты

2024/04/23 00:00 ••• alextretyak
Признаки устаревшего языка

2024/04/21 00:00 ••• alextretyak
Постфиксные инкремент и декремент

2024/04/20 21:28 ••• Бурановский дедушка
Русский язык и программирование

2024/04/07 15:33 ••• MihalNik
Все языки эквивалентны. Но некоторые из них эквивалентнее других

2024/04/01 23:39 ••• Бурановский дедушка
Новости и прочее

2024/04/01 23:32 ••• Бурановский дедушка
Русской операционной системой должна стать ReactOS

2024/03/22 20:41 ••• void
Раскрутка компилятора

2024/03/20 19:54 ••• kt
О многократном резервировании функций

2024/03/20 13:13 ••• Неслучайный читатель
Надёжные программы из ненадёжных компонентов

2024/03/07 14:16 ••• Неслучайный читатель
«Двухмерный» синтаксис Python

2024/03/03 16:49 ••• Автор сайта
О неправомерном доступе к памяти через указатели

2024/02/28 18:59 ••• Вежливый Лис
Про лебедей, раков и щук