Тест "Счастливые билеты" для других платформ

В записи Тест "Счастливые билеты" приводятся результаты для ПМК, но в комментариях накопилось немало полезных примеров для некалькуляторных платформ. Все они перенесены в эту новую запись.

Метки публикаций: 

Комментарии

Сделал тест "счастливых билетов" под мультиклетовский си-компилятор:

//schastlivye bilety
#include 
#include 
void main()
{
	int a;
  int b;
  int c;
  int d;
  int e;
  int f;
  int g;
  int h=0x00007000;
	WDT_OFF;
  while(1)
  {
    GPIOD->DIR = ((uint32_t)0x00007000);
    GPIOD->OUT = ((uint32_t)h);
    g=0;
    for (a=10; a>=1; a--)
    {
      for (b=10; b>=1; b--)
      {
        for (c=10; c>=1; c--)
        {
          for (d=10; d>=1; d--)
          {
            for (e=10; e>=1; e--)
            {
              for (f=10; f>=1; f--)
              {
                if ((a+b+c)==(d+e+f)) g++;
              }
            }
          }
        }
      }
    }
    if (g==55252)
    h^=0x00007000;
  }
}

Результат ажно 0,84 секунды при тактовой частоте процессора 80МГц, получившееся быстродействие порядка 10млн. операций в секунду, это очень мало! Ежели выкинуть выражение if ((a+b+c)==(d+e+f)) g++; то время выполнения программы падает вдвое, всё-таки распараллеливание операций по клеткам есть, но сама компиляция организована не лучшим образом! Даже если учесть отсутствие распараллеливания из-за циклов, то производительность должна быть всё равно минимум почти на порядок выше!
Вердикт: пока лучше грызть ассемблер!

Оптимизировал алгоритм, время расчёта уменьшилось до 0,78с:

//schastlivye bilety
#include 
#include 

void main()
{
	int a;
  int b;
  int c;
  int d;
  int e;
  int f;
  int g;
  int h=0x00007000;
  int i;
  int j;
  int k;
	WDT_OFF;
	
  while(1)
  {
    GPIOD->DIR = ((uint32_t)0x00007000);
    GPIOD->OUT = ((uint32_t)h);
    g=0;
    for (a=10; a>=1; a--)
    {
      for (b=10; b>=1; b--)
      {
        i=a+b;
        for (c=10; c>=1; c--)
        {
          j=i+c;
          for (d=10; d>=1; d--)
          {
            for (e=10; e>=1; e--)
            {
              k=d+e;
              for (f=10; f>=1; f--)
              {
                if (j==(k+f)) g++;
              }
            }
          }
        }
      }
    }
    if (g==55252)
    h^=0x00007000;
  }
}

Сделал "Счастливые билеты" на мультиклетовском асме, я прямо в недоумении от результата... Порядка 30 млн. оп./с. Ещё особенность программрования на асме вылезла - внутри микропрограммы не должно быть больше одной ссылки на одну микропрограмму, а также больше одной ссылки на один и тот же регистр. Может быть ветвление, но со ссылками на разные микропрограммы. Можно подумать по оптимизации программы, но похоже сильно много не выжмешь, миллион пустых циклов выполняются за 0,22 секунды, всё равно как-то не вяжется с 80МГц. Похоже время жрёт подгрузка микропрограмм в ядро. Операнды целочисленные, использовались только регистры общего назначения.

Тест на ардуине к моему изумлению дал 0,78с при частоте ATMega328P 16МГц!

int led = 13;
byte a;
byte b;
byte c;
byte d;
byte e;
byte f;
word g;
boolean h=false;
byte i;
byte j;
byte k;
void setup() {
  pinMode(led, OUTPUT);
}
void loop() 
{	
    g=0;
    for (a=10; a>=1; a--) {
      for (b=10; b>=1; b--) {
        i=a+b;
        for (c=10; c>=1; c--) {
          j=i+c;
          for (d=10; d>=1; d--) {
            for (e=10; e>=1; e--) {
              k=d+e;
              for (f=10; f>=1; f--) {
                if (j==(k+f)) g++;
              }
            }
          }
        }
      }
    }
    if (g==55252) 
    h=!h;
    digitalWrite(led, h);
}

А вот миллион пустых циклов выполняется ажно 6 секунд, так что ардуиновый компилятор весьма неоднозначен.

В России весной 2017 выпустили отечественную плату на основе миландровского микроконтроллера марки К1986ВЕ92QI, а в качестве IDE разработчики платы взяли бесплатную NetBeans со своими дополнениями.

Время выполнения теста при тактовой частоте 80МГц составило 0,105с, то есть всего 105мс! В среднем, на выполнение главного цикла уходит шесть операций, плюс операция на внешние циклы, то получается, что результирующее быстродействие на уровне 67 млн. оп/с, то есть, по тактам, порядка 83% от теоретического, хотя если считать по даташиту в 1,25 млн. оп./с. на 1МГц, то выходит 67% теоретического быстродействия!

#include "main.h"
#include "stdlib.h"
#include "stdio.h"
#include "mstn_led.h"

uint a;
uint b;
uint c;
uint d;
uint e;
uint f;
uint g;
//uint h;
uint j;
uint i;
uint k;
    
void bilety();

int main()
{
    LED_SetGreenState(TURN_ON);
    while(1)
    {
        bilety();
        if (g==55252)
        LED_SetRedState(TURN_ON);
        if (g==55252)
        bilety();
        LED_SetRedState(TURN_OFF);
    }
    return EXIT_SUCCESS;
}

void bilety()
{
    g=0;
    for (a=10; a>=1; a--)
    {
        for (b=10; b>=1; b--)
        {
            i=a+b;
            for (c=10; c>=1; c--)
            {
                j=i+c;
                for (d=10; d>=1; d--)
                {
                    for (e=10; e>=1; e--)
                    {
                        k=d+e;
                        for (f=10; f>=1; f--)
                        {
                            if (j==(k+f)) g++;
                        }
                    }
                }
            }
        }
    }
}

Поскольку флешпамять микроконтроллера имеет задержку в четыре такта, хоть и разбита на четыре параллельно работающих банка, я думаю, что код программы компилятор вполне мог поместить в оперативную память микроконтроллера. Кстати, есть один тонкий момент, у ядра ARM Cortex-M3 есть несколько команд, выполняющих по две операции за такт, например умножение плюс сложение, поэтому такие впечатляющие результаты могут получаться за счёт архитектурных особенностей микроконтроллера. Впечатляюще, не правда, ли?

Результат рассчитывается честно, не 55251, и не 55253, а честных 55252 билета)

Добавлено. Разобрался с функциями и переменными, выложил обновлённый тест, результаты прежние.

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

Попробуй полностью отключить оптимизацию у компилятора. Там наверняка GNU C, он с этой задачкой справляется на уровне -o2 очень неплохо.

Пробовал я вместо набора команд С11 ставить С89 и С99, вместо режима оптимизации О2 ставил О0, результаты такие же. А потом я вместо 80МГц поставил 16МГц и что же?! Тоже самое, и нагрев кристалла остался прежним! Похоже, настроенный интэковцами компилятор нагло игнорит все мои поползновения в сторону уменьшения оптимизации при компиляции программы. Добавлю, что в Кейле тактовая частота действительно устанавливалась 16МГц и микросхема была холодной.

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

А вот написание программы выполнения миллионов пустых циклов, не дало возможности измерить период выполнения, период расчёта можно измерить только осциллографом или частотомером. По-видимому интеллекта оптимизатора хватает на то, чтобы обратить внимание на миллион пустых вычислений, и, по-видимому, в готовой программе меняется алгоритм, для подгонки результата! Поэтому миллион пустых циклов можно считать заведомо не пригодным для оценки эффективности компиляторов, которые его могут просто обходить.

Прошу извинения за ошибочную оценку. И никто мордой не ткнул)

Допущенная ошибка в попытке оценить время выполнения миллиона пустых циклов дала интересный побочный результат. Миллион операций вывода одного дискретного бита в порт микроконтроллера на основе библиотеки stdio.h выполняется за 0,84с то есть порядка 1,2 млн оп. выв. /с. Если оценить затраты на цикл в три операции, то выходит, что функция вывода в порт выполняется от 20 (по тактам) до 25 (по даташиту) операций!

#include "main.h"
#include "stdlib.h"
#include "stdio.h"
#include "mstn_led.h"

int main()
{
    uint a;
    LED_SetGreenState(TURN_ON);
    while(1)
    {
        a=0;
        for (a=1000000; a>=1; a--)
        LED_SetRedState(TURN_ON);
        a=0;
        for (a=1000000; a>=1; a--)
        LED_SetRedState(TURN_OFF);
    }
    return EXIT_SUCCESS;
}

Добавлено.

Скомпилировал вот такой код:

#include "main.h"
#include "stdlib.h"
#include "stdio.h"
#include "mstn_led.h"

int main()
{
    uint a;
    LED_SetGreenState(TURN_ON);
    while(1)
    {
        a=0;
        for (a=1000000; a>=1; a--);
        LED_SetRedState(TURN_ON);
        a=0;
        for (a=1000000; a>=1; a--);
        LED_SetRedState(TURN_OFF);
    }
    return EXIT_SUCCESS;
}

Итого, время выполнения цикла... 2деления х 2мкс/дел х 0,2 множитель развертки, итого... 0,8мкс... В общем, затраты времени только на операцию вывода бита в порт.

фото

Прошу специалистов прокомментировать код, по-моему где-то я ошибся.

Не рассматривали такую особенность современных ARM-ов? Это сильно может сбить ввод-вывод.

А как конвейер может уменьшить выполнение функции for (a=1000000; a>=1; a--); до ста тактов? Где я ошибся?

вообще выбросить ваш пустой цикл из бинарника

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

[quote=Ватник]вообще выбросить ваш пустой цикл из бинарника[/quote]

А это легко проверить - посмотреть lst файл.

[quote=Электромонтёр]А как конвейер может уменьшить выполнение функции for (a=1000000; a>=1; a--); до ста тактов? Где я ошибся?[/quote]

Предсказание переходов, очень даже может.

Написал php-скрипт для MB77.07 на микросхеме К1879ХБ1Я. Результат: 1,98 с на частоте 324МГц. В зависимости от нагрузки на процессор, значение несколько меняется. С учётом быстродействия ядра ARM1176JZF-S на уровне 1,25 DMIPS/MHz эффективность составляет 0,9%. Пожалуй, php5-fpm 5.6.38 это рекорд неэффективности?

<?рhp
function microtime_float()
{
    list($usec, $sec) = explode(" ", microtime());
    return ((float)$usec + (float)$sec);
}
$a=0;
$b=0;
$c=0;
$d=0;
$e=0;
$f=0;
$g=0;
$h=0;
$i=0;
$j=0;
$k=microtime_float();
for ($a=10; $a>=1; $a--) {
	for ($b=10; $b>=1; $b--) {
		$g=$a+$b;
		for ($c=10; $c>=1; $c--) {
			$h=$g+$c;
			for ($d=10; $d>=1; $d--) {
				for ($e=10; $e>=1; $e--) {
					$i=$d+$e;
					for ($f=10; $f>=1; $f--) {
						if ($h==($i+$f)) $j++;
					}
				}
			}
		}
	}
}
$k=microtime_float()-$k;
echo "Счастливых билетов: $j шт.";
echo "<Ьr>";
echo "Время расчёта: $k с.";
echo "<Ьr>";
?>

Обновлено: - рекорд побит Питоном.

Ну так то же интерпретируемый PHP. Интересно было бы сравнить на Питоне, запущенном на этом же микрокомпьютере.

И Похапэ и Питон компилируются в П-код, выполняемый на своей виртуальной машине/процессоре. Разница в производительности может иметь место, но не принципиальная.

Отослал тест Антону Прибора -

Я проестировал этот алгоритм на пхп и на си. На моём i5 сишный вариант оказался в 500 раз быстрее пхпшного)) Правда, как писать сайты на си я не знаю...

Зато, судя по первой же статье, Антон знает, почему надо писать плохой код :) Прикладного программиста от сохи видно за версту.

[quote=Serguei_Tarassov]И Похапэ и Питон компилируются в П-код, выполняемый на своей виртуальной машине/процессоре. Разница в производительности может иметь место, но не принципиальная.[/quote]
Да, поэтому мне и интересно узнать, кто из этих байт-кодных машин быстрее :)

Тест на Ruby 2.1.15 Процессор тот же, результат:
4.997081869
Руби занимает второе место по неэффективности - 0,35%
Вот сам скрипт:

a=0
b=0
c=0
d=0
e=0
f=0
g=0
h=0
i=0
j=0
k=Time.new
for a in 0..9
for b in 0..9
g=a+b
for c in 0..9
h=g+c
for d in 0..9
for e in 0..9
i=d+e
for f in 0..9
if h==i+f
j=j+1
end
end
end
end
end
end
end
k=Time.new-k
puts j
puts k

Обновлено: рекорд побит Питоном.

Python 3.4.2 дал наихудший результат - от 14 до 20 секунд, в среднем 17:
_
Эффективность - 0,13%! Питон с достоинством занимает первое место моего хит-парада по неэффективности :)
РНР-то оказывается не так уж и плох :)
Почему-то заметный разброс, у PHP и Ruby порядка, ±5% а у питона достигает ±15%

Скрипт:

a=0
b=0
c=0
d=0
e=0
f=0
g=0
h=0
i=0
j=0
from datetime import datetime
k=datetime.now()
for a in range(10):
	for b in range(10):
		g=a+b
		for c in range(10):
			h=g+c
			for d in range(10):
				for e in range(10):
					i=d+e
					for f in range(10):
						if h==i+f:
							j=j+1
k=datetime.now()-k
print (j)
print (k)

Стоит отдать должное - у Питона довольно удобный синтаксис. Однако, за удобство приходится платить кровью производительностью. Если выполнение теста требует 7 млн. операций и занимает 14 секунд, то в результате от 405млн (324х1,25) оп./с остаётся жалкие 0,5 млн. оп./с. А это значит, что благодаря Питону российская 90-нм СБИС К1879ХБ1Я 2010 года скатывается до советской 6-мкм БИС К580ИК80 1977 года, на 33 года назад!

На десерт запустил тест на бортовом Perl 5.20.2, cредний результат 9,5 с:

_

Эффективность - 0,18%.
Скрипт:

$a=0;
$b=0;
$c=0;
$d=0;
$e=0;
$f=0;
$g=0;
$h=0;
$i=0;
$j=0;
$k=time();
for ($a=10; $a>=1; $a--) {
	for ($b=10; $b>=1; $b--) {
		$g=$a+$b;
		for ($c=10; $c>=1; $c--) {
			$h=$g+$c;
			for ($d=10; $d>=1; $d--) {
				for ($e=10; $e>=1; $e--) {
					$i=$d+$e;
					for ($f=10; $f>=1; $f--) {
						if ($h==($i+$f)) {
							$j++;
						}
					}
				}
			}
		}
	}
}
$k=time()-$k;
print($j);
print"\n";
print($k);
print"\n";

Получается, из всех скриптовых интерпретаторов наименьшим злом является Rubi, вдвое хуже - Perl и втрое - Python.

тоже интересно бы было :)

Проверил вышеупомянутый скрипт на Питоне3 под BeagleBone Black, AM335x 1GHz ARM® Cortex-A8:

debian@beaglebone:~/Sandbox$ python3 py3tickets.py
55252
0:00:03.437071

А вообще было интересно увидеть, что ПХП быстрее Питона. Мнда

Ядро ARM1176 СБИС К1879ХБ1Я имеет производительность 1,25DMIPS/MHz, а ARM Cortex-A8 2,0 DMIPS/MHz, то есть AM335x на 1ГГц должно быть впятеро производительнее ARM-ядра К1879ХБ1Я на 324МГц. Если у меня на Питоне минимальный результат был 14с, то у тебя должно получится 2,8с :) Хотя, если учитывать среднее значение 17с, то получается в аккурат 3,4с :)

А вообще было интересно увидеть, что ПХП быстрее Питона.

Да, получилось значительно быстрее :)

Второй питон побыстрее тут:

debian@beaglebone:~/Sandbox$ python py3tickets.py
55252
0:00:01.857202
debian@beaglebone:~/Sandbox$ python3 py3tickets.py
55252
0:00:03.415652

Да разница двухкратная полуторная.
_
Простой довнгрейд буквально вдвое улучшил обстановку :) Вот не ожидал!
Обновлено: Путём многократного запуска теста, преимущество второго питона оказалось не столь значительно.

На RaspberryPi Zero иначе: 5.3 и 5.1 сек соответственно:

pi@raspberrypi:~/PythonStuff $ python tickets.py
55252
0:00:05.366339
pi@raspberrypi:~/PythonStuff $ python3 tickets.py
55252
0:00:05.084681

"Малинка" Zero на 1GHz ARM11 процессоре.

Вполне согласуется с моими результатами, у К1879ХБ1Я частота втрое ниже.
Для чистоты эксперимента перепрошил микрокомпьютер. В общем, руби как был 5 секунд, так и остался, перл 10 с, второй питон 9-11с, третий питон 14-17с. Второй питон больше разброс даёт.

Для логического завершения экспериментов по тестированию эффективности различных интерпретаторов по предложению Vitasam провёл тест "Счастливые билеты", скомпилированные компилятором GCC. Вот тестовая программа:

#include
#include
char a;
char b;
char c;
char d;
char e;
char f;
char g;
char h;
char i;
unsigned short j;
float k;
float l;
int main() {
k=clock();
    j=0;
    for (a=10; a>=1; a--) {
      for (b=10; b>=1; b--) {
        g=a+b;
        for (c=10; c>=1; c--) {
          h=g+c;
          for (d=10; d>=1; d--) {
            for (e=10; e>=1; e--) {
              i=d+e;
              for (f=10; f>=1; f--) {
                if (h==(f+i)) j++;
              }
            }
          }
        }
      }
    }
k=clock()-k;
l=k/CLOCKS_PER_SEC;
printf("%d",j);
printf("\n");
printf("%f",l,"\n");
printf("\n");
return 0;
}

Поскольку, GCC имеет регулировку оптимизации, я проверил на всех доступных уровнях- по умолчанию, О0, О1, О2 и О3:

Тест проводился на ARM1176 ядре СБИС К1879ХБ1Я, работающем на частоте 324 МГц и обладающий усреднённой производительностью 324х1,25 = 405 млн.оп/с.
Итак, результат оптимизации по умолчанию - 0,174 с, быстродействие - 40 млн.оп./с, эффективность - 10%. Что-то не очень, хотя уже в десять раз быстрее php и в 81 раз быстрее python 3.

Результат с выключенной оптимизации О0 тот же - 0,174 с, быстродействие - 40 млн.оп./с, эффективность - 10%. Очевидно, в gcc по умолчанию оптимизация отключена.

Результат с начальной оптимизацией О1 в семь раз лучше - 0,024 с, быстродействие - 290 млн.оп./с, эффективность - 72%. Вот это уже похоже на правду, вот она мощь процессора!

Результат со средней оптимизацией О2 - 0,02 с, быстродействие - 350 млн.оп./с, эффективность - 86%. Можно сказать, что результат приближается к ассемблерному.

Наконец, максимальное ускорение! Результат с наибольшей оптимизацией О3 поражает - 0,014 с, быстродействие - 500 млн.оп./с, эффективность - 123% :) Чудес не бывает, а вечный двигатель построить ещё никому не удалось. Компилятор явно развернул внутренний цикл.

По результатам экспериментов тиснул статейку :)
З.Ы. Если кто найдёт простую реализацию ЧПУ на RaspberryPi вместо GRBL на ардуине, дайте ссылку. Простую - это значит, как на ардуине, залил прошивку и работай, безо всяких сборок и перекомпиляций ядра из сорцов :)

Хорошее исследование!

А про простую реализацию ЧПУ на Raspberry. Имеется в виду чтобы без операционки?
Тогда надо смотреть в сторону Bare Metal программирования.

Это образ с ЧПУ программой, чтобы залил и работай.

А ЧПУ существует под Линукс/Распберри? В таком случае проще всего сделать просто образ SD-карточки. PiBakery, к примеру.

Да, есть LinuxCNC, требует специально пропатченного ядра для реалтайма, и меньше и хуже документирован чем Mach3. Натыкался на видео на ютубе, как рационализатор на заводе переделывал советский ЧПУ станок с разбомблённой НЦ-31 на LinuxCNC, правда до автосмены инструмента он не дошёл.

Запуск скомпилированного GCC теста на уровне -О2 из скрипта РНР!
Сам скрипт предельно прост:

<?php
function microtime_float()
{
    list($usec, $sec) = explode(" ", microtime());
    return ((float)$usec + (float)$sec);
}
$t=microtime_float();
$p=exec('./tickets');
$t=microtime_float()-$t;
echo "Счастливых билетов: $p шт.";
echo "
"; echo "Время расчёта: $t с."; echo "
"; ?>

Но из скрипта запускается заранее скомпилированный со средним уровнем оптимизации файл:

#include
#include
char a;
char b;
char c;
char d;
char e;
char f;
char g;
char h;
char i;
unsigned short j;
int main() {
    j=0;
    for (a=10; a>=1; a--) {
      for (b=10; b>=1; b--) {
        g=a+b;
        for (c=10; c>=1; c--) {
          h=g+c;
          for (d=10; d>=1; d--) {
            for (e=10; e>=1; e--) {
              i=d+e;
              for (f=10; f>=1; f--) {
                if (h==(f+i)) j++;
              }
            }
          }
        }
      }
    }
printf("%d",j,"\n");
return 0;
}

Результат - 0,06с, и из них только треть тратится на расчёт!

Недостаток - только одно значение можно вывести. Выход - из скомпилированной программы писать в файл, а уже из файла читать данные скриптом.

А в чем смысл использования "больше или равно" и декремента в циклах?

for (a=10; a>=1; a--) 

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

Подозреваю, что современные архитектуры давно уже имеют соответствующие single-операторы для таких сравнений. Ну, и компиляторы умные. Так что да, писать код нынче надо для удобства понимания и обслуживания кода*, а оптимизацией займется компилятор.

(* в разумных пределах, конечно же).

Декрементный цикл лучше, если только выполняется до нуля.
for(i=10; i; i--)
код ассемблера
mov i, 10
cycle:
...
dec i
jnz cycle

Неудивительно, в ПХП вложены миллионы от корпораций типа Фейсбука, которым важно разогнать виртуальную машину до предела для обеспечения производительности нагруженных приложений. Питон для этого практически не используется, это современный аналог Бейсика для быстрой прикладной разработки программ любителями под свои задачи.

С другой стороны, странно. Data mining и ИИ, в основном, на Питоне сейчас пилятся. Видимо, удобство языка перевешивает

Не пишут, а настраивают. Типа, ядро нейросетки на Си, а обучающие скрипты на питоне.

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

это современный аналог Бейсика для быстрой прикладной разработки программ любителями под свои задачи.

Ну таки не только любителями :)

Тут интересная статья про орбитальный телескоп-искатель экзопланет "Кеплер". Все основные программные инструменты, используемые для обработки данных с телескопа, написаны на Питоне (и они почти все выложены на Гитхабе):

  1. Lightkurve — Lightkurve Python позволяет эффективно анализировать данные временных рядов астрономических потоков, в частности пикселей и световых кубов, полученных миссиями NASA Kepler, K2 и TESS. Ссылка.
  2. PyKE — Набор инструментов командной строки для проверки данных и извлечения кривых звездного блеска. Ссылка.
  3. K2fov — Набор инструментов командной строки для проверки файлов „целевого пикселя“ и выделения скрытых световых кубов. Ссылка.
  4. K2ephem — Проверяет, сможет ли движущееся тело Солнечной системы, астероид или комета, попасть в „поле зрения“ системы. Ссылка.
  5. K2flix — Преобразует файлы целевых пикселей в видео или анимированные gif-файлы для быстрой и легкой оценки таких пикселей. Ссылка.
  6. K2mosaic — Преобразует файлы целевого пикселя в изображения с широким полем. Ссылка.
  7. Kadenza — Преобразует первичные данные в FITS, удобные для астрономов. Ссылка.

Тест на моём DEXP Ixion P135 с процессором MT6572A 2x Cortex-A7 1 ГГц на Android 4.4.2 с расчётной производительностью 2х1900 млн.оп./с. Компилятор - мобильный С 2.5.2, 2013 год.
Код использован от МВ77.07:

Результат - 5,05 мc, производительность - 1385 млн.оп./с.

Поскольку программа явно выполняется на одном ядре, то эффективность кода мобильного компилятора выходит - 73%.
Не ожидал от андройда такой прыти :) но компиляция программы жрёт в сто раз больше - полсекунды :(

Сделал максимальную оптимизацию. Было около 5000000 тактов, стало 6-7 тыс тактов. Убрал вложенные циклы. В общем, потом подробней информацию выложу, с смартфона это сделать сложно!

//////////////////////////////////////////////////////////////////;
// Тест Счастливые билеты.  v0.01
// (c) NanoBot
// Создан: 3.09.‎2021 23:21     Изменения: 4.09.‎2021 ‏‎0:56
//////////////////////////////////////////////////////////////////;
#include stdio.h
#include intrin.h

int main()
{
    unsigned int    count;                  //кол. счастливых билетов.
    unsigned int    sum_l, sum_r;           //суммы левой и правой части
    unsigned char   l3, l2, l1, r3, r2, r1; //счётчики сотен, десятков и единиц левой и правой части
    unsigned __int64    tics;
    printf("TEST: Happy tickets.\n");
    tics = __rdtsc();
    for(l3=0, sum_l=0, count=0; l3<10; l3++, sum_l-=9)
        for(l2=0; l2<10; l2++, sum_l-=9)
            for(l1=0; l1<10; l1++, sum_l++)
                for(r3=0, sum_r=0; r3<10; r3++, sum_r-=9)
                    for(r2=0; r2<10; r2++, sum_r-=9)
                        for(r1=0; r1<10; r1++, sum_r++)
                            count += sum_l==sum_r;
    tics = __rdtsc() - tics;
    printf("Count tickets = %d, tics = %lld\n", count, tics);
    return 0;
}

Код хорош тем, что интеллектуальный оптимизатор может очень сильно оптимизировать код, вплоть до просто формулы. Сейчас хочу сделать программу для МК-61, чтобы ПМК смог за небольшое время подсчитать вариант 3+3. Или даже 4+4! Да МК-61!!!

Сделал оптимизацию на 8 этапов.
https://yadi.sk/d/zFoikkKNw2hDQw
Меняем дефайн OPTIMIZATION от 0 до 8 чтобы выбрать нужную оптимизацию.