Длина, скорость и частота электромагнитной волны.
Онлайн калькулятор перевода длины волны в частоту для широкого диапазона частот, включая радиоволны, микроволны, инфракрасное излучение, видимый свет, ультрафи- олетовое излучение, рентгеновские и гамма лучи.
Рис.1
Время, за которое волна успевает преодолеть это расстояние (λ), т. е. интервал времени, за который периодический колебательный процесс повторяется, называется периодом колебаний, обозначается буквой ፐ (тау) или Т и измеряется в метрах.
Частота электромагнитных колебаний связана с периодом простейшим соотношением:
f (Гц) = 1 / T (сек) .
Скорость распространения электромагнитных волн в вакууме (v) равна скорости света и составляет величину: v = С = 299792458 м/сек .
В среде эта скорость уменьшается: v = С / n , где n > 1 — это показатель преломления среды.
Абсолютный показатель преломления любого газа (в том числе воздуха) при обычных условиях мало чем отличается от единицы, поэтому с достаточной точностью его можно не учитывать в условиях распространения электромагнитных волн в воздушном пространстве.
Соотношение, связывающее длину волны со скоростью распространения в общем случае, выглядит следующим образом:
λ (м) = v (м/сек) *Т (сек) = v (м/сек) / f (Гц) .
И окончательно для воздушной среды:
λ (м) = 299792458 *Т (сек) = 299792458 / f (Гц) .
Прежде чем перейти к калькуляторам, давайте рассмотрим шкалу частот и длин волн непрерывного диапазона электромагнитных волн, которая традиционно разбита на ряд поддиапазонов. Соседние диапазоны могут немного перекрываться.
Диапазон | Полоса частот | Длина волны |
Сверхдлинные радиоволны | 3. 30 кГц | 100000. 10000 м |
Длинные радиоволны | 30. 300 кГц | 10000. 1000 м |
Средние радиоволны | 300. 3000 кГц | 1000. 100 м |
Короткие радиоволны | 3. 30 МГц | 100. 10 м |
Метровый радиодиапазон | 30. 300 МГц | 10. 1 м |
Дециметровый радиодиапазон | 300. 3000 МГц | 1. 0,1 м |
Сантиметровый СВЧ диапазон | 3. 30 ГГц | 10. 1 см |
Микроволновый СВЧ диапазон | 30. 300 ГГц | 1. 0,1 см |
Инфракрасное излучение | 0,3. 405 ТГц | 1000. 0,74 мкм |
Красный цвет | 405. 480 ТГц | 740. 625 нм |
Оранжевый цвет | 480. 510 ТГц | 625. 590 нм |
Жёлтый цвет | 510. 530 ТГц | 590. 565 нм |
Зелёный цвет | 530. 600 ТГц | 565. 500 нм |
Голубой цвет | 600. 620 ТГц | 500. 485 нм |
Синий цвет | 620. 680 ТГц | 485. 440 нм |
Фиолетовый цвет | 680. 790 ТГц | 440. 380 нм |
Ультрафиолетовое излучение | 480. 30000 ТГц | 400. 10 нм |
Рентгеновское излучение | 30000. 3000000 ТГц | 10. 0,1 нм |
Гамма излучение | 3000000. 30000000 ТГц | 0,1. 0,01 нм |
А теперь можно переходить к калькуляторам.
КАЛЬКУЛЯТОР РАСЧЁТА ДЛИНЫ ВОЛНЫ ПО ЧАСТОТЕ
КАЛЬКУЛЯТОР РАСЧЁТА ЧАСТОТЫ ПО ДЛИНЕ ВОЛНЫ
Микросекунды в Наносекунд
Конвертировать из Микросекунды в Наносекунд. Введите сумму, которую вы хотите конвертировать и нажмите кнопку конвертировать.
1 Микросекунды = 1000 Наносекунд | 10 Микросекунды = 10000 Наносекунд | 2500 Микросекунды = 2500000 Наносекунд |
2 Микросекунды = 2000 Наносекунд | 20 Микросекунды = 20000 Наносекунд | 5000 Микросекунды = 5000000 Наносекунд |
3 Микросекунды = 3000 Наносекунд | 30 Микросекунды = 30000 Наносекунд | 10000 Микросекунды = 10000000 Наносекунд |
4 Микросекунды = 4000 Наносекунд | 40 Микросекунды = 40000 Наносекунд | 25000 Микросекунды = 25000000 Наносекунд |
5 Микросекунды = 5000 Наносекунд | 50 Микросекунды = 50000 Наносекунд | 50000 Микросекунды = 50000000 Наносекунд |
6 Микросекунды = 6000 Наносекунд | 100 Микросекунды = 100000 Наносекунд | 100000 Микросекунды = 100000000 Наносекунд |
7 Микросекунды = 7000 Наносекунд | 250 Микросекунды = 250000 Наносекунд | 250000 Микросекунды = 250000000 Наносекунд |
8 Микросекунды = 8000 Наносекунд | 500 Микросекунды = 500000 Наносекунд | 500000 Микросекунды = 500000000 Наносекунд |
9 Микросекунды = 9000 Наносекунд | 1000 Микросекунды = 1000000 Наносекунд | 1000000 Микросекунды = 1000000000 Наносекунд |
Встроить этот конвертер вашу страницу или в блог, скопировав следующий код HTML:
Измерение времени с наносекундной точностью
Пару месяцев назад для меня наступил исторический момент. Мне перестало хватать стандартных средств операционной системы для измерения времени. Понадобилось измерять время с наносекундной точностью и с наносекундными накладными расходами.
Я решил написать библиотеку, которая решала бы эту задачу. На первый взгляд казалось, что и делать-то особо нечего. Но при более детальном рассмотрении, как всегда, выяснилось, что есть много интересных проблем, с которыми предстояло разобраться. В этой статье я расскажу и о проблемах, и о том, как они были решены.
Так как на компьютере можно измерять много разных типов времени, сразу уточню, что здесь речь пойдет о «времени по секундомеру». Или wall-clock time. Оно же real time, elapsed time и т.п. То есть простое «человеческое» время, которое мы засекаем в начале исполнения задачи и останавливаем в конце.
Микросекунда – почти вечность
Разработчики высокопроизводительных систем за последние несколько лет уже привыкли к микросекундному масштабу времени. За микросекунды можно прочитать данные с NVMe-диска. За микросекунды данные можно переслать по сети. Не по всякой, конечно, но по InifiniBand-сети – запросто.
При этом у микросекунды появилась еще и структура. Полный стек ввода-вывода состоит из нескольких программных и аппаратных компонент. Задержки, вносимые некоторыми из них, лежат на суб-микросекундном уровне.
Для измерения задержек такого масштаба микросекундная точность уже недостаточна. Однако важна не только точность, но еще и накладные расходы на измерение времени. Линуксовый системный вызов clock_gettime() возвращает время с наносекундной точностью. На машине, которая вот прямо сейчас у меня под рукой (Intel® Xeon® CPU E5-2630 v2 @ 2.60GHz), этот вызов отрабатывает примерно за 120 нс. Очень неплохая цифра. К тому же clock_gettime() работает достаточно предсказуемо. Это позволяет учесть накладные расходы на его вызов и в действительности делать измерения с точностью порядка десятков наносекунд. Однако обратим теперь внимание вот на что. Чтобы измерить интервал времени, нужно сделать два таких вызова: в начале и в конце. Т.е. потратить 240 нс. Если измеряются плотно расположенные промежутки времени порядка 1-10мкс, то в некоторых таких случаях сам процесс измерения будет значительно искажать наблюдаемый процесс.
Я начал этот раздел с того, как ускорился IO-стек в последние годы. Это новая, однако далеко не единственная причина хотеть измерять время быстро и точно. Такая необходимость была всегда. Например, всегда существовал код, который хотелось ускорить хотя бы на 1 такт микропроцессора. Или вот еще пример, из оригинальной статьи про нашумевшую уязвимость Spectre:
Здесь в строках 72-74 измеряется время исполнения одной-единственной операции обращения к памяти. Правда, Spectre не интересуют наносекунды. Время может быть измерено в «попугаях». К попугаям и секундам мы еще вернемся.
Time-stamp counter
Ключ к быстрому и точному измерению времени – специальный счетчик микропроцессора. Значение этого счетчика обычно хранится в отдельном регистре и обычно – но не всегда – доступно из пользовательского пространства. На разных архитектурах счетчик называется по-разному:
Прочитать значение TSC обычно – но опять же не всегда – можно с помощью одной-единственной инструкции. Вот пример для x86. Строго говоря, это не чистая ассемблерная инструкция, а inline-ассемблер GNU:
Инструкция «rdtsc» помещает две 32-битных половинки регистра TSC в регистры eax и edx. Из них можно «склеить» единое 64-битное значение.
Еще раз отмечу: эту (и подобные) инструкции в большинстве случаев можно вызвать прямо из пользовательского пространства. Никаких системных вызовов. Минимум накладных расходов.
Что теперь нужно сделать, чтобы измерить время?
Время, измеренное по описанной процедуре, выражено в «попугаях». Оно не в секундах. Но иногда попугаи – это именно то, что нужно. Бывают ситуации, когда важны не абсолютные значения интервалов времени, а то, как различные интервалы соотносятся друг с другом. Приведенный выше пример со Spectre демонстрирует ровно такую ситуацию. Длительность каждого отдельного обращения к памяти значения не имеет. Важно только, что обращения по одним адресам будут исполнены значительно быстрее, чем по другим (в зависимости о того, хранятся ли данные в кеше или основной памяти).
А что если нужны не попугаи, а секунды/микросекунды/наносекунды и т.п.? Тут можно выделить два принципиально разных случая:
Time-stamp counter-ы не так просты, как нам хотелось бы. На некоторых архитектурах:
Из-за перечисленных выше проблем TSC не может служить надежным источником времени на некоторых системах. Однако на других системах, «страдающих» от тех же проблем, TSC все же можно использовать. Это становится возможным благодаря специальным архитектурным фишкам:
Итак, существует множество архитектурных реализаций TSC, каждая со своими особенностями. Но интересно, что во всем этом зоопарке установился общий тренд. Современные железо и операционные системы стремятся гарантировать, что:
Библиотека
Я не стал закладываться на аппаратные фишки кучи разных архитектур. Вместо этого я решил, что моя библиотека будет ориентирована на современный тренд. У нее чисто эмпирический фокус:
В коде можно посмотреть детали реализации всех методов, о которых далее пойдет речь.
Оценка надежности TSC
Библиотека предоставляет интерфейс, который возвращает две оценки:
Эту оценку я ниже буду называть оценкой монотонности TSC
Посмотрим теперь, как можно получить первую оценку:
Два метода сбора значений счетчиков
В библиотеке я реализовал два метода сбора значений TSC:
Оценки надежности, получаемые с мощью этого метода, выглядят уже очень неплохо. Например, оценка максимально сдвига получается уже на уровне нескольких сотен тиков. А проверка монотонности позволяет поймать рассинхронизацию часов в пределах сотни тиков.
Однако алгоритмы, приведенные в предыдущем разделе, не подходят для этого метода. Для них важно, чтобы значения TSC были измерены в заранее определенном порядке. Метод «замеров, упорядоченных с помощью CAS» не позволяет этого сделать. Вместо этого, сначала собирается длинная последовательность случайных измерений, и затем алгоритмы (уже другие) пытаются найти в этой последовательности значения, прочитанные на «подходящих» CPU.
Я не буду приводить здесь эти алгоритмы, чтобы не злоупотреблять вашим вниманием. Их можно посмотреть в коде. Там много комментариев. Идейно эти алгоритмы те же самые. Принципиально новый момент – это проверка того, насколько статистически «качественными» являются случайно набранные последовательности TSC. Также возможно задать минимально приемлемый уровень статистической значимости для оценок надежности TSC.
Теоретически, на ОЧЕНЬ больших системах метод «замеров, упорядоченных с помощью CAS» может давать плохие результаты. Метод требует, чтобы процессоры состязались за доступ к общей ячейке памяти. Если процессоров очень много, то состязание может получиться очень напряженным. В результате, будет сложно создать последовательность измерений с хорошими статистическими свойствами. Однако на данный момент такая ситуация выглядит маловероятной.
Я обещал немного кода. Вот как выглядит выстраивание замеров в единую цепочку с помощью CAS.
Еще один момент, о котором стоит здесь упомянуть – это забота о том, чтобы все потоки, занимающиеся измерениями, стартанули более-менее одновременно. Мы заинтересованы в том, чтобы значения TSC, прочитанные на разных CPU, были как можно лучше перемешаны между собой. Нас не устроит ситуация, когда, например, сначала запустится один поток, закончит свою работу, и только потом запустятся все остальные. У результирующей последовательности TSC будут никудышные свойства. Из нее не получится извлечь никаких оценок. Одновременный старт всех потоков важен – и для этого в библиотеке приняты меры.
Конвертация тиков в наносекунды «на лету»
После проверки надежности TSC, второе большое назначение библиотеки – это конвертация тиков в наносекунды на лету. Идею этой конвертации я позаимствовал из уже упомянутого fio. Однако мне пришлось внести несколько существенных улучшений, потому что как показал мой анализ, в самом fio процедура конвертации работает недостаточно хорошо. Там получается низкая точность.
Сразу начну с примера.
В идеале, конвертировать тики в наносекунды хотелось бы вот так:
ns_time = tsc_ticks / tsc_per_ns
Мы хотим, чтобы время, затрачиваемое на конвертацию, было минимальным. Поэтому мы нацелены на использование исключительно целочисленной арифметики. Посмотрим, чем это может нам грозить.
Если множитель factor достаточно большой, то и точность будет хорошей. Но кое-что останется плохим. А именно, накладные расходы на конвертацию. Целочисленное деление – это очень дорогая операция. Например, на x86 она требует 10+ тактов. Плюс к тому, операции целочисленного деления не всегда конвейеризуются.
Первое деление – не проблема. Мы можем предвычислить (factor / 3.333) заранее. А вот второе деление – по-прежнему боль. Чтобы избавиться от нее, давайте выберем factor равным степени двойки. После этого второе деление можно будет заменить на битовый сдвиг – простую и быструю операцию.
ns_time = (tsc_ticks * 512 / 3.333) / 512
ns_time = tsc_ticks * 153 / 512
Это большая ошибка. Мы хотим лучшей точности. Что если мы будем измерять интервалы времени не более часа? Я опущу выкладки. Они совершенно идентичны только что проделанным. Окончательная формула будет:
ns_time = tsc_ticks * 1258417 / 4194304 (1)
Ошибка конвертации составит лишь 119305 наносекунд на 1 час (что меньше 0.2 миллисекунды). Очень и очень неплохо. Если же максимальное конвертируемое значение будет еще меньше, чем час, то и точность будет еще лучше. Но как нам это использовать? Не ограничивать же измерения времени одним часом?
Обратим внимание на следующий момент:
tsc_ticks = (tsc_ticks_per_1_hour * number_of_hours) + tsc_ticks_remainder
Готово. Такой механизм конвертации нас устраивает. Давайте теперь его обобщим и оптимизируем.
Прежде всего, мы хотим иметь гибкий контроль над ошибками конвертации. Мы не хотим привязывать параметры конвертации к интервалу времени в 1 час. Пусть это будет произвольный интервал времени:
tsc_ticks = modulus * number_of_moduli_periods + tsc_ticks_remainder
Еще раз вспомним, как конвертировать остаток в наносекунды:
ns_per_remainder = (tsc_ticks_remainder * factor / tsc_per_nsec) / factor
Вычислим параметры конвертации (мы знаем, что tsc_ticks_remainder ):
modulus * (factor / tsc_per_nsec)
Занудства ради, надо отметить, что последнее неравенство не эквивалентно первому в рамках целочисленной арифметики. Но я не буду на этом надолго останавливаться. Скажу только, что последнее неравенство более жесткое, чем первое, и поэтому безопасно для использования.
factor = 2 ^ shift
mult = factor / tsc_per_nsec
И дальше эти параметры используются для конвертации остатка в наносекунды:
ns_per_remainder = (tsc_ticks_remainder * mult) >> shift
modulus = 2 ^ remainder_bit_length
ns_per_moduli = ns_per_modulus * number_of_moduli_periods
ns_per_modulus = (modulus * mult) >> shift
Все! Мы смогли предвычислить все параметры, необходимые для конвертации тиков в наносекунды «на лету». Суммируем теперь кратенько процедуру конвертации:
Если вы все еще читаете этот пост, то вы большой или большая молодец. Возможно даже, что вы performance-аналитик или разработчик высокопроизводительного софта.
Так вот. Оказывается, мы еще не закончили 🙂
mult = factor / tsc_per_nsec
mult = factor * 1000000000 / tsc_per_sec
И тут есть два интересных вопроса:
Делается это на основе прямого измерения:
start_sytem_time = clock_gettime()
start_tsc = WTMLIB_GET_TSC()
подождать сколько-то времени
end_system_time = clock_gettime()
end_tsc = WTMLIB_GET_TSC()
Заключение
Но тема эффективного измерения времени на этом не исчерпывается. Есть много нюансов. Заинтересованным предлагаю самостоятельно проработать следующие вопросы:
tp->tv_sec = nsecs / 1000000000ULL;
Получается, что сначала TSC тики конвертируются в наносекунды с помощью быстрой и эффективной процедуры. А потом весь выигрыш нивелируется за счет целочисленного деления, которое нужно, чтобы из наносекунд выделить секунды
Рассмотренные в этой статье методы позволяют измерять время масштаба секунды с точностью порядка нескольких десятков наносекунд. Это та точность, которую я реально наблюдаю при использовании своей библиотеки.
Интересно, что fio, из которого я позаимствовал некоторые методы, на масштабе секунды теряет в точности порядка 700-900 наносекунд (и тому есть целых три причины). Плюс теряет в скорости конвертации из-за хранения времени в стандартном линуксовом формате. Однако спешу успокоить фанатов fio. Я отправил разработчикам описание всех проблем с конвертацией, которые обнаружил. Люди уже работают, скоро исправят.
Желаю всем много приятных наносекунд!
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.