#c #performance #time #runtime #cumulative-sum
#c #Производительность #время #время выполнения #кумулятивная сумма
Вопрос:
Я реализовал метод c , который вычисляет максимальную ошибку ulp между аппроксимацией и эталонной функцией на заданном интервале. Приближение, а также ссылка вычисляются как значения с плавающей запятой одинарной точности. Метод начинается с нижней границы интервала и повторяется по каждому существующему значению с одинарной точностью в пределах диапазона.
Поскольку существует множество существующих значений в зависимости от выбранного диапазона, я хотел бы оценить общее время выполнения этого метода и распечатать его пользователю.
Я попытался выполнить сравнение несколько раз, чтобы вычислить время выполнения одной итерации. Мой подход заключался в том, чтобы умножить продолжительность одной итерации на общее количество плавающих значений, существующих в диапазоне. Но, очевидно, время выполнения для одной итерации не является постоянным, а зависит от количества итераций, поэтому моя предполагаемая продолжительность вообще не точна… Может быть, можно было бы адаптировать вычисление общего времени выполнения в основном цикле?
Мой вопрос: есть ли какой-либо другой способ оценить общее время выполнения для этого конкретного случая?
Вот мой код:
void FloatEvaluateMaxUlp(float(*testFunction)(float), float(*referenceFunction)(float), float lowBound, float highBound)
{
/*initialization*/
float x = lowBound, output, output_ref;
int ulp = 0;
long long duration = 0, numberOfFloats=0;
/*calculate number of floats between lowBound and highBound*/
numberOfFloats = *(int*)amp;highBound - *(int*)amp;lowBound;
/*measure execution time of 10 iterations*/
int iterationsToEstimateTime = 1000;
auto t1 = std::chrono::high_resolution_clock::now();
for (int i = 0; i < iterationsToEstimateTime; i )
{
printProgressInteger(i 1, iterationsToEstimateTime);
output = testFunction(x);
output_ref = referenceFunction(x);
int ulp_local = FloatCompareULP(output, output_ref);
if (abs(ulp_local) > abs(ulp))
ulp = ulp_local;
x= std::nextafter(x, highBound 0.001f);
}
auto t2 = std::chrono::high_resolution_clock::now();
duration = std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count();
duration /= iterationsToEstimateTime;
x = lowBound;
/*output of estimated time*/
std::cout <<std::endl<<std::endl<< " Number of floats: " << numberOfFloats << " Time per iteration: " << duration << " Estimated total time: " << numberOfFloats * duration << std::endl;
std::cout << " Starting test in range [" << lowBound << "," << highBound << "]." << std::endl;
long long count = 0;
/*record start time*/
t1 = std::chrono::high_resolution_clock::now();
for (count; x < highBound; count )
{
printProgressInteger(count, numberOfFloats);
output = testFunction(x);
output_ref = referenceFunction(x);
int ulp_local = FloatCompareULP(output, output_ref);
if (abs(ulp_local) > abs(ulp))
ulp = ulp_local;
x = std::nextafter(x, highBound 0.001f);
}
/*record stop time and compute duration*/
t2 = std::chrono::high_resolution_clock::now();
duration = std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count();
/*result output*/
std::cout <<std::endl<< std::endl << std::endl << std::endl << "*********************************************************" << std::endl;
std::cout << " RESULT " << std::endl;
std::cout << "*********************************************************" << std::endl;
std::cout << " Iterations: " << count << " Total execution time: " << duration << std::endl;
std::cout << " Max ulp: " << ulp <<std::endl;
std::cout << "*********************************************************" << std::endl;
}
Комментарии:
1. Для получения более точной оценки вам потребуется больше данных. Некоторые из ваших проблем или препятствий будут связаны с переключением задач операционной системой. Другим может быть разрешение ваших часов или измерительного устройства. Помните, что современные процессоры выполняют инструкции в диапазоне наносекунд. Если вы выполните больше итераций, вы можете преобразовать свои измерения во что-то более надежное, например, в миллисекунды или секунды. К сожалению, часы не справляются с этой скоростью. Другой вопрос заключается в разрешении часов операционной системы, часы H / W могут иметь более высокое разрешение, но часы операционной системы могут и не иметь.
2. В мире встроенных систем для профилирования используются осциллографы и логические анализаторы. Код записывается в контрольную точку (или другое устройство, к которому может подключаться прибор, например, светодиод). Одним из примеров является то, что код утверждает контрольную точку в начале измерения, а затем отменяет ее в конце измерения. Обычно эти инструменты имеют достаточно точное время для измерения одной инструкции. В качестве среднего значения будет выполнено более одного измерения для устранения выбросов и шума. Мы бы использовали среднее значение выборок из инструментов.
3. Поскольку у вас, вероятно, нет измерительных приборов или контрольных точек, вам нужно будет выполнить не менее 1E06 итераций между измерениями часов, чтобы получить значимое среднее значение. Опять же, вы хотите устранить выбросы и шумы в операционной системе. В статистике одной выборки никогда не бывает достаточно.
4. Спасибо за ваше объяснение! Вы правы, у меня нет ни измерительных приборов, ни контрольных точек, это невозможно. Итак, я прав, предполагая, что вы бы порекомендовали установить iterationsToEstimateTime равным 1e6 для устранения шума и т.д.?
5. Как говорится в статистике, чем больше данных, тем лучше среднее качество.