ЧАСТЬ 7 — БЫСТРЕЕ, ЧЕМ BASIC
Автор: Иэн Калл (Ian Cull Bsc)
Часть 1. Введение.
Компьютер Sinclair ZX Spectrum, как и почти все компьютеры, построен вокруг Центрального Процессора — микропроцессорного чипа Z80. Этот чип представляет собой очень маленький кусочек кремния в корпусе размером примерно 3 на 1 дюйм и способен выполнять до четырех миллионов операций КАЖДУЮ секунду! ZX Spectrum не запускает Z80 на полной скорости, но тем не менее может выполнять сотни тысяч операций каждую секунду. Так почему же ваша программа на Basic работает так медленно?
Ответ заключается в том, что чип Z80 способен понимать только очень простые инструкции, которые ничего не говорят ни вам, ни мне. Например, следующие инструкции складывают 2 и 7 :-
00111110
00000010
11000110
00000111
и ZX Spectrum может делать это около 250000 раз каждую секунду! К сожалению, когда вы пишите следующую программу на Basic :-
10 LET A=2+7
ZX Spectrum успевает выполнить эту операцию только около 385 раз в секунду. Проблема в том, что понятный нам с вами Basic ничего не значит для Z80. Специальные программы в ZX Spectrum преобразуют наш Basic в инструкции, которые Z80 может понять, и именно так выполняется наша программа.
Конечно, на это преобразование уходит ОЧЕНЬ много времени для Z80, так как он способен выполнять лишь очень простые вещи. Именно поэтому программа на Basic выдает результаты в 500 или 1000 раз дольше, чем программа для Z80.
Тем не менее, существует ряд способов заставить наши программы работать быстрее, и в этой серии мы рассмотрим, как делать вещи «быстрее, чем (ZX) Basic».
Уловки.
ZX Spectrum Basic — очень «дружелюбный» к пользователю Basic, и любой, кто пользовался компьютерами не от Sinclair, подтвердит это. ZX Spectrum Basic проверяет каждую строку программы по мере её ввода. Вы также можете остановить программу, изменить её и продолжить выполнение (большинство версий Basic теряют все переменные при любом изменении).
К сожалению, ZX Spectrum Basic также ОЧЕНЬ медленный. Большинство идентично написанных программ будут работать навскидку намного медленнее на ZX Spectrum, чем на многих других компьютерах. Причины этого сложны, но они вызваны тем, как создавался ZX Spectrum Basic (в основном путём прикручивания дополнений к ранним версиям для ZX80 и ZX81).
Однако, если вы знаете особенности ZX Spectrum Basic, вы можете изменить свои программы так, чтобы они работали быстрее. Вот три примера :-
- a) Сначала определяйте переменные, которые используются чаще всего. Когда программа будет обращаться к ним, ZX Spectrum Basic найдет их быстрее.
- b) Поместите часто используемые подпрограммы и циклы в начало вашей программы (и используйте GO TO для обхода их стороной) — ZX Spectrum Basic всегда ищет подпрограммы с самого начала программы.
- c) Избегайте «сложных» инструкций, если можно обойтись простыми. Например, умножение на два для Z80 происходит намного медленнее, чем прибавление числа к самому себе.
Эти и другие «уловки» могут быть применены в любой программе и дадут больший или меньший эффект в зависимости от того, что делает программа (например, очень короткая программа не сильно ускоряется от пункта b).
Альтернативные языки.
Basic (Beginners All-purpose Symbolic Instruction Code — Универсальный код символических инструкций для начинающих) изначально разрабатывался для обучения Фортрану и проектировался так, чтобы его было легко учить, а не чтобы он был эффективен в использовании. Basic очень хорош в некоторых задачах (в частности, при работе со строками), но плох во многих других (например, попробуйте обработать больше данных, чем помещается в памяти).
Существует множество других компьютерных языков, созданных для самых разных целей, и вы обнаружите, что написание программы на языке, отличном от Basic, часто дает гораздо более быстрые результаты. Конечно, на это может уйти гораздо больше времени — именно поэтому Basic все еще популярен как «быстрое и грязное» решение для многих задач; если компьютер тратит много времени на выполнение программы, на написание которой у вас ушло гораздо меньше времени, значит, самое время выпить еще кофе! В этой серии мы рассмотрим другие языки, доступные для ZX Spectrum, в частности, насколько они быстрее Basic по сравнению с тем, насколько сложнее на них писать.
Машинный код.
Способ заставить ваши программы работать ДЕЙСТВИТЕЛЬНО быстро — это написать их на языке, который понимает Z80.
Этот язык называется Машинным кодом, и его действительно трудно изучать и писать. Пример, который я привел ранее, — это экстремальный способ написания машиннного кода: фактические двоичные представления инструкций.
Хотя эти единицы и нули — это всё, что понимает Z80, задача облегчается, если мы используем Ассемблер — это программа, которая выполняет прямое (один к одному) преобразование написанных нами программ на ассемблере в машинный код. Более ранняя программа на ассемблере выглядит так :-
LD A,2
ADD A,7
Очевидно, что нам это понять проще, чем фактический машинный код, но это не решает проблему того, что Z80 умеет делать только очень простые вещи — мы должны разбивать нашу программу на сотни простейших инструкций.
Компиляторы.
Здесь, в теории, кроется ответ на все мечты (и то, чему на самом деле посвящена эта серия). Компилятор немного похож на Ассемблер тем, что он берет программу и выдает машинный код. Разница в том, что программа может быть написана на языке, который вы уже знаете — например, на Basic! Компиляторы бывают очень простыми или очень сложными, в зависимости от того, сколько уловок в них запрограммировано. На самом простейшем уровне каждая строка программы преобразуется в точно эквивалентный набор инструкций машинного кода — прирост скорости происходит исключительно благодаря тому, что перевод из программы в машинный код выполняется компилятором заранее, а не по ходу выполнения программы. С другой стороны, Компиляторы могут часами рыться в вашей программе, удаляя ненужный код, переставляя фрагменты и в целом создавая машинный код, который может работать почти так же быстро, как если бы вы написали программу на ассемблере самостоятельно.
Чтобы получить некоторое представление о том, каких улучшений можно ожидать при использовании другого языка или компилятора, мы используем «бенчмарки» (тесты производительности). Это простые программы, которые могут быть написаны на любом компьютерном языке и замеряются по времени выполнения — это время дает представление о том, насколько полезен язык или компилятор для реальных задач. Проблема бенчмарков в том, что они проверяют только то, для чего написаны — что НЕ является реальной задачей. Некоторые компиляторы могут даже распознавать стандартные тестовые программы-бенчмарки и «читерить» (жульничать), переписывая тест. Тем не менее, я собираюсь использовать в этих тестах несколько «действительно полезных» бенчмарков — программы будут вычислять первую сотню простых чисел (чисел, которые делятся нацело только на самих себя или на единицу — действительно полезно!) Существует две программы, которые делают одно и то же совершенно разными способами.
PRIMES1 вычисляет каждое простое число, проверяя все деления (это очень медленная и сложная задача для Z80). PRIMES2 использует «решето», что похоже на вычеркивание из списка всех кратных каждого числа; любые числа, которые не были вычеркнуты, должны быть простыми (попробуйте сами, если сомневаетесь).
В этом месяце мы завершаем статью публикацией обоих листингов на ZX Spectrum Basic. Попробуйте их на своем компьютере (и на других компьютерах, если можете) и попытайтесь их подкрутить — посмотрите, как быстро вы заставите их работать. Обратите внимание, что удаление строки PRINT (160 в PRIMES1, 130 в PRIMES2) делает сравнение более чешским, поскольку в этом случае замеряется не вывод на экран, а только вычисления (ZX Spectrum ОЧЕНЬ медленно выводит вещи на экран).
В качестве затравки для поддержания интереса: в одном из последующих выпусков PRIMES2 (без вывода PRINT) будет работать около половины секунды — это примерно в сто раз Быстрее, чем Basic...
10 REM PRIMES1 in Basic. Ian Cull Bsc. 18/
4/89.
20 DIM P(1000)
30 LET P(1)=2: LET PTOP=1
40 LET PP=1: LET PPS=P(PP)*P(PP)
50 LET P=3
100 IF PPS<100 THEN GOTO 200
110 IF P(PTOP)<>0 THEN LET PTOP=PTOP+1: GO
TO 100
120 LET P=PTOP: LET X=P
130 PRINT PCNT,P: INPUT; :REM Remove this
for speed
140 LET PCNT=PCNT+1
150 LET P(X)=1: LET X=X+P
160 IF X<=1000 THEN GOTO 150
170 GOTO 100
200 PRINT"Prime 100 is ";P: STOP
Присоединяйтесь к нам в следующем месяце для изучения Части 2 учебника.
Поделитесь вашим мнением о статье