Сформировать массив B из произведения соседних элементов A по следующему правилу: B0=A0 * Am, B1=A1 * Am, ..., где m – либо номер первого четного отрицательного элемента массива А, либо номер последнего элемента, если в массиве А нет отрицательных элементов.
- Есть исходный код на си, скомпилированный с разными опциями, шаги рефакторинга ассемблероного кода пропущены т.к. писалась программа на ассемблере с нуля.
- Есть сравнительные тесты показывающие скорость работы обоих программ.
- Есть генератор случайных чисел с указанием границ
- Есть ввод-вывод из файла
- Есть измерение времени работы программы
- Есть текст программы на языке ассемблера без использования си функций
- Весь ассемблерный код содержит поясняющие комментарии
/asm
содержит исходный код на ассембеле без использования си функций/asm/lib
содержит файлы с дополнительными функциями-
array.s
- работа с массивами
-
io.s
- ввод/вывод из консоли/файлов
-
str.s
- работа со строками
-
time.s
- замер времени
-
rand.s
- генерация случайных чисел
/asm/main.s
- главный файл программы/c-stuff
содержит исходный код на языке си и результаты его компиляции/tests
папка с тестами- Файл
make-tests.py
позволяет создавать тесты необходимой длины
make compile ; компилирует все дополнительные библиотеки
make build ; компилирует основой код с добавлением библиотек
Далее, чтобы запустить ручной ввод/вывод необходимо выполнить просто ./main
. Для ввода и вывода в файл необходимо укзаать два аргумента ./main <input_file> <output_file>
. Для работы с генератором случайных чисел необходимо набрать ./main -r <count> <lower_bound> <upper_bound> <output_file>
. В таком случае на экран будет выведен сгенерированный массив.
Во всех случаях ограничение на длину массива 100000000 элементов. При вводе большего числа будет выведено сообщение. Ограничения на сами элементы нет. Но если будут введены числа по модулю большие чем long
то не гарантируется верный ответ.
gcc main.c -o main
В си программе отсутствует ручной ввод вывод. Для ввода и вывода необходимо укзаать два аргумента ./main <input_file> <output_file>
. Для работы с генератором случайных чисел необходимо набрать ./main -r <count> <lower_bound> <upper_bound> <output_file>
.
- В папке
tests
нет тестов на 100000000 чисел из за большого размера файла. - Файлы которые подаются в вход программе должны содержать перенос строки в конце. Пример:
5
1
2
3
4
5
В обоих случая надо при запуске указать параметры. Пример:
$ ./main -r 20 -20 20 out.txt
-1 -11 5 2 -20 2 3 -13 5 17 -20 15 18 -6 -13 9 0 0 20 20
Elapsed time:
Read: 0.0
Calculations: 0.239
Write: 0.92549
Выведется сгеренированный массив длиной 20 с значениями от -20 до 20, а в файл out.txt
будет помещен результат выполнения.
- Обычный тест где нет четного отрицательного
./main ../tests/test1.txt out.txt
5
1
2
3
4
5
Результат
5
10
15
20
25
- Обычный тест где есть четное отрицательное
./main ../tests/test2.txt out.txt
5
1
-2
3
4
5
Результат
-2
4
-6
-8
-10
- Обычный тест где есть отрицательное но оно не четное
./main ../tests/test3.txt out.txt
5
1
-3
3
4
5
Результат
5
-15
15
20
25
- Обычный тест где нет четного отрицательного
./main ../tests/test1.txt out.txt
5
1
2
3
4
5
Результат
5
10
15
20
25
- Обычный тест где есть четное отрицательное
./main ../tests/test2.txt out.txt
5
1
-2
3
4
5
Результат
-2
4
-6
-8
-10
- Обычный тест где есть отрицательное но оно не четное
./main ../tests/test3.txt out.txt
5
1
-3
3
4
5
Результат
5
-15
15
20
25
Результаты работы программ совпадают
- Размер исполняемого файла
- Размер ассемблероного файла сгенерированного из си кода при помощи флагов
-masm=intel -fno-asynchronous-unwind-tables -fno-jump-tables -fno-stack-protector -fno-exceptions -Os
составляет всего 243 строки. А с оптимизацией-Ofast
377 строк. В то же время размер самописной программы на ассемблере составляет 413 строк в main файле + 530 строк в вспомогательных файлах. Однако размер исполняемого файла на ассемблере составляет 7,1K а у программы на си 13K, а с флагом-Os
тоже 13K.
- Время работы программ
- Тестировалась работа программ написанных на ассемблере, на си, на ассемблероном коде, скомпилированным при помощи флага
-Ofast
, а так же при помощи флага-Os
. - На тесте в 100000 элементов:
asm c: -Ofast asm -Os asm
--------------------------------------------------------------
Read: 0.78601389 | 0.004616 | 0.004694 | 0.004389
Calculations: 0.263031 | 0.000126 | 0.000140 | 0.000115
Write: 0.287058676 | 0.004586 | 0.004624 | 0.003961
- На тесте в 1000000 элементов:
asm: c: -Ofast asm -Os asm
-------------------------------------------------------------
Read: 0.727040354 | 0.044912 | 0.046473 | 0.045780
Calculations: 0.2503454 | 0.001279 | 0.001220 | 0.001285
Write: 2.433563873 | 0.044850 | 0.044344 | 0.041114
- На тесте в 10000000 элементов:
asm: c: -Ofast asm -Os asm
--------------------------------------------------------------
Read: 7.362924217 | 0.508615 | 0.447636 | 0.439966
Calculations: 0.22556240 | 0.053719 | 0.010598 | 0.012137
Write: 25.433004001 | 0.516155 | 0.452513 | 0.442933
- На тесте в 100000000 элементов:
asm: c: -Ofast asm -Os asm
-------------------------------------------------------------
Read: 72.466802783 | 5.043507 | 4.470650 | 4.498052
Calculations: 0.957936372 | 0.553682 | 0.136249 | 0.115879
Write: 256.506313724| 5.078061 | 4.506198 | 4.125936
- Обработка некорректных данных
- Количество элементов больше 100000000
-
- Обе программы выводят сообщение об ошибке
Length is greater than 100000000!
- Обе программы выводят сообщение об ошибке
- Вводимые элементы не помещаются в
long
-
- В обоих случаях
undefined behavior
- В обоих случаях
- Указанного файла не существует
-
- Программа на си выводит сообщение с ошибкой, программа на ассемблере выведет сообщение об ошибке и укажет код ошибки
Error while opening a file: 2
. В данном случае 2 означаетNo such file or directory
.
- Программа на си выводит сообщение с ошибкой, программа на ассемблере выведет сообщение об ошибке и укажет код ошибки
Компилятор gcc осказался умнее меня. Скорость работы программы на чистом ассемблере оказалась меньше чем на си с разницей до 4-х раз. При этом время на операции ввода и вывода оказалось в среднем в 50 раз больше. Размер исполняемого файла на ассемблере оказлся меньше чем на си. При этом, написание когда на ассемблее во много раз дольше.