Хотел бы добавить, что для таких измерений вообще можно снять объектив и светить монитором напрямую в матрицу (если он конечно съёмный), тогда будет минимум пятен от пыли на объективе, виньетирования и прочего. И можно провести полноценную offset + dark калибровку (а не только offset), чтоб как раз убрать те самые горячие пиксели, хотя не уверен, что они внесут какой-либо значительный вклад на малых выдержках.
Ещё есть некоторые соображения на тему выбора ISO. Так как изменение ISO никак не влияет на количество электронов на детекторе и просто усиливает уже собранный сигнал, но уменьшает динамический диапазон, то оптимальным значением будет минимальное iso, которое позволит превысить шум ADC. Данное значение не обязательно будет единичным усилением (unity gain) и может быть как меньше (для малошумящих ADC), так и больше (для сильно шумящих). Конечно это только для случая, когда мы можем компенсировать всё длинной выдержкой, но для сильно шумящих ADC всё равно имеет смысл поднимать ISO выше единичного усиления, т.к. шум просто все съест.
Расходы на вызов, возврат, перекладывание данных в нужные регистры, через которые передаются параметры в функцию, прочие манипуляции, описанные в ABI.
Но все эти накладные расходы не важны, когда прошивка не помещается в МК, не зря inline на -Os не включается, и вообще компилятор сам решает, встраивать функцию или нет. Заставить его можно через forceinline, только скорее всего это плохая идея.
И для того, что описано в стаье inline не подходит, т.к. он именно встраивает функцию по месту вызова, и если встраивание не удалось (например, куда встраивать обработчик прерывания?), то пролог и эпилог никуда не денутся.
inline именно про встраивание функции в тело другой функции и ключевым словом является только в С++, оно не имеет никакого отношения к удалению пролога и эпилога. Тут нужен именно naked.
С некоторыми оговорками, ближайший аналог из Си это #define. Встроенную функцию можно лучше оптимизировать и нет никаких накладных расходов на вызов (т.к. по-факту не происходит ни вызова ни возврата из встроенной функции), но бинарник от этого может довольно значительно распухнуть, т.к. функция будет поставлена во все места, где она вызывается.
Могу еще предположить, что при преобразовании выражения x+x*y в x*(1-y) нам надо прозвести деление, что-то типа x*(1 + x*y/x), а в вычислениях с плавающей точкой это не всегда можно выполнить без потери точности. Ну и это начинает оказывать сильное влияние, т.к. потеря точности происходит на последней итерации, т.е. в самом значимом слагаемом ряда.
По поводу точности sin_e4, там для малых x суммирование с 1 будет убивать точность, а в sin_e5 происходит суммирование более-менее сопоставимых величин.
Попытался воспроизвести сравнение на своей машине, но ни порядок величин, ни харатер зависимости не совпали ни для CPU ни для GPU.
Характаристики
CPU :Intel® Core(TM) i7-4790K CPU @ 4.00GHz (8 cores)
ОЗУ:32гбDDR4
GPU:GeForce GTX 1060 6GB
OS: Ubuntu 18.04 LTS
Cuda:
Compute Capability 6.1
Threads per Multiprocessor 1024
CUDA 10.2
Тестовый скрипт
cat run.sh
#!/bin/bash
dataset=("1679616\n500" "18143994\n2500" "82301184\n6500" "136048896\n8500" "123119982\n9500" "377913600\n14500")
echo "test GPU"
nvcc --version
nvcc test.cu
for data in ${dataset[*]}
do
printf $data > input.txt
cat input.txt
echo ""
time ./a.out
done
echo "test CPU"
g++ --version
g++ -O3 test.cpp -pthread
for data in ${dataset[*]}
do
printf $data > input.txt
cat input.txt
echo ""
time ./a.out
done
Сырой вывод скрипта
./run.sh
test GPU
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2019 NVIDIA Corporation
Built on Wed_Oct_23_19:24:38_PDT_2019
Cuda compilation tools, release 10.2, V10.2.89
1679616
500
6^8=1679616
36^4=1679616
real 0m0.141s
user 0m0.037s
sys 0m0.093s
18143994
2500
no value
real 0m0.349s
user 0m0.206s
sys 0m0.138s
82301184
6500
no value
real 0m1.525s
user 0m1.122s
sys 0m0.401s
136048896
8500
108^4=136048896
real 0m2.557s
user 0m1.910s
sys 0m0.645s
123119982
9500
no value
real 0m3.227s
user 0m2.500s
sys 0m0.719s
377913600
14500
no value
real 0m7.147s
user 0m5.497s
sys 0m1.648s
test CPU
g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1679616
500
6^8=1679616
36^4=1679616
real 0m0.053s
user 0m0.251s
sys 0m0.028s
18143994
2500
no value
real 0m0.806s
user 0m5.932s
sys 0m0.051s
82301184
6500
no value
real 0m5.214s
user 0m40.169s
sys 0m0.056s
136048896
8500
108^4=136048896
real 0m8.926s
user 1m8.601s
sys 0m0.052s
123119982
9500
no value
real 0m11.008s
user 1m25.921s
sys 0m0.136s
377913600
14500
no value
real 0m25.551s
user 3m20.153s
sys 0m0.160s
Результат (почему-то не сработал табличный markdown)
Сложно сказать, почему 1060 оказался в 10 раз быстрее 2060 и Intel в 4 раза быстрее AMD (но может быть конечно честные 8 ядер в 4 раза быстрее чем 4ядра*2потока).
Суперкомпьютер конечно не требуется, но одним Orbiter'ом дело не ограничивается. Orbiter это только внешнее окружение, дающее влияние атмосферы, гравитации и прочих сил.
Чтоб провести полноценную симуляцию тех алгоритмов, что написаны для Союза и Фрегата, нужно написать модели обеих систем со всеми датчиками, двигателями и прочим. В идеале они должны уметь загружать и исполнять непосредственно прошивки этих блоков. Эта задача несколько более масштабная чем просто ракету в Orbeter'е запустить. Но в целом подъемная и нужна, особенно с учетом стоимости ошибок.
Добрый день!
Тема интересная, продолжайте!
Хотел бы добавить, что для таких измерений вообще можно снять объектив и светить монитором напрямую в матрицу (если он конечно съёмный), тогда будет минимум пятен от пыли на объективе, виньетирования и прочего. И можно провести полноценную offset + dark калибровку (а не только offset), чтоб как раз убрать те самые горячие пиксели, хотя не уверен, что они внесут какой-либо значительный вклад на малых выдержках.
Ещё есть некоторые соображения на тему выбора ISO. Так как изменение ISO никак не влияет на количество электронов на детекторе и просто усиливает уже собранный сигнал, но уменьшает динамический диапазон, то оптимальным значением будет минимальное iso, которое позволит превысить шум ADC. Данное значение не обязательно будет единичным усилением (unity gain) и может быть как меньше (для малошумящих ADC), так и больше (для сильно шумящих). Конечно это только для случая, когда мы можем компенсировать всё длинной выдержкой, но для сильно шумящих ADC всё равно имеет смысл поднимать ISO выше единичного усиления, т.к. шум просто все съест.
Расходы на вызов, возврат, перекладывание данных в нужные регистры, через которые передаются параметры в функцию, прочие манипуляции, описанные в ABI.
Но все эти накладные расходы не важны, когда прошивка не помещается в МК, не зря inline на -Os не включается, и вообще компилятор сам решает, встраивать функцию или нет. Заставить его можно через forceinline, только скорее всего это плохая идея.
И для того, что описано в стаье inline не подходит, т.к. он именно встраивает функцию по месту вызова, и если встраивание не удалось (например, куда встраивать обработчик прерывания?), то пролог и эпилог никуда не денутся.
inline именно про встраивание функции в тело другой функции и ключевым словом является только в С++, оно не имеет никакого отношения к удалению пролога и эпилога. Тут нужен именно naked.
С некоторыми оговорками, ближайший аналог из Си это #define. Встроенную функцию можно лучше оптимизировать и нет никаких накладных расходов на вызов (т.к. по-факту не происходит ни вызова ни возврата из встроенной функции), но бинарник от этого может довольно значительно распухнуть, т.к. функция будет поставлена во все места, где она вызывается.
Попытался воспроизвести сравнение на своей машине, но ни порядок величин, ни харатер зависимости не совпали ни для CPU ни для GPU.
Compute Capability 6.1
Threads per Multiprocessor 1024
CUDA 10.2
Результат (почему-то не сработал табличный markdown)
Сложно сказать, почему 1060 оказался в 10 раз быстрее 2060 и Intel в 4 раза быстрее AMD (но может быть конечно честные 8 ядер в 4 раза быстрее чем 4ядра*2потока).
Чтоб провести полноценную симуляцию тех алгоритмов, что написаны для Союза и Фрегата, нужно написать модели обеих систем со всеми датчиками, двигателями и прочим. В идеале они должны уметь загружать и исполнять непосредственно прошивки этих блоков. Эта задача несколько более масштабная чем просто ракету в Orbeter'е запустить. Но в целом подъемная и нужна, особенно с учетом стоимости ошибок.