О вводе-выводе, скорость и корректность
Nov. 11th, 2016 10:43 pmДочка сдаёт задачи по программированию, как это сейчас модно, через e-judge и аналогичные системы.
Первая задача: много вывода. Лимит времени работы в системе - 100 мс. На моём десктопе показывает 45 мс. Вывод через
Вторая задача: очень много ввода (максимум теоретически возможного по условиям - 20 миллионов intʼов). fscanf даёт 1.2 секунды. Ручная замена на враппер вокруг getc() - ~0.2 секунды. Лимит в системе тот же - 100мс. Всё равно много. Вытаскивает вчерашний вариант на Паскале, исправляет ошибки, отправляет. Проходит. Сравниваю время после локального freepascal. 3 миллисекунды(!)
Сначала я подумал, что случилось чудо и паскалевцы сумели оптимизировать до предела. Но решил посмотреть внимательнее. Когда ktrace показывает, что из файла на 10M целых читается только 256 байт... мягко говоря, странно. Пропущу пляски с бубном, но результат раскопок: во FreePascal двухбайтный integer. Соответственно, 10000000 превратилось на чтении обычным read(n) в... -27008. Последующий цикл чтения
Посмотрел, что там longint - 4 байта, заменил все integer на него. Время работы на те же 20M целых поднялось до 1.7 секунды. Что ж, отсутствие чуда уже доказано.
Вот как можно на таких допотопных средствах детей учить?
Первая задача: много вывода. Лимит времени работы в системе - 100 мс. На моём десктопе показывает 45 мс. Вывод через
cout << val. Вспоминаю рассказы про тормознутость iostreams, подсказываю про stdio. Переписывает, сдаёт. Локально время сократилось до 2 мс. В целевой системе - прошло.Вторая задача: очень много ввода (максимум теоретически возможного по условиям - 20 миллионов intʼов). fscanf даёт 1.2 секунды. Ручная замена на враппер вокруг getc() - ~0.2 секунды. Лимит в системе тот же - 100мс. Всё равно много. Вытаскивает вчерашний вариант на Паскале, исправляет ошибки, отправляет. Проходит. Сравниваю время после локального freepascal. 3 миллисекунды(!)
Сначала я подумал, что случилось чудо и паскалевцы сумели оптимизировать до предела. Но решил посмотреть внимательнее. Когда ktrace показывает, что из файла на 10M целых читается только 256 байт... мягко говоря, странно. Пропущу пляски с бубном, но результат раскопок: во FreePascal двухбайтный integer. Соответственно, 10000000 превратилось на чтении обычным read(n) в... -27008. Последующий цикл чтения
for i:=1 to n тупо выполнился ноль раз. А тесты как раз сошлись так, чтобы повторить эту ошибку.Посмотрел, что там longint - 4 байта, заменил все integer на него. Время работы на те же 20M целых поднялось до 1.7 секунды. Что ж, отсутствие чуда уже доказано.
Вот как можно на таких допотопных средствах детей учить?
no subject
Date: 2016-11-12 09:04 am (UTC)no subject
Date: 2016-11-12 12:25 pm (UTC)Когда ученик вместо алгоритма должен гадать, влезет ли число в integer - это помеха. Когда чтение тайно обрезает число без предупреждения - помеха в кубе.
Для сравнения - в Яве попытка Scanner.nextInt() на 2147483648 даёт исключение. Это хуже, чем в Python прозрачное держание чисел до 2**1016-1, но лучше, чем молчаливое урезание.