SQL ЗАКАЗАТЬ `no` с NULL в конце

Соглашение о вызове Windows x86-64 с только 6 списками xmm с записью с записью не очень хорошее, вы правы. Большинство SIMD (и многих скалярных FP) циклов не содержат каких-либо вызовов функций, поэтому они ничего не получают от того, что их данные хранятся в сохраняемых вызовах. Сохранение / восстановление - это чистый недостаток, потому что это редкость, чем любой из их вызывающих пользователей использует это энергонезависимое состояние.

В x86-64 System V все векторные регистры сбрасываются по вызову, что может быть, слишком далеко. Во многих случаях было бы хорошо сохраниться 1 или 2 вызова, особенно для кода, который вызывает некоторые вызовы функций библиотеки. ( Используйте gcc -fno-math-errno, чтобы упростить простые строки , иногда единственная причина, по которой они не делают, - это установить errno на NaN.)

Связано: , как было выбрано соглашение о вызове x86-64 SysV : просмотр размера кода и подсчета команд для gcc-компиляции SPECint / SPECfp.


Для целых регистров, имеющих некоторые из них, определенно хорошо, и все «обычные» соглашения о вызовах (для всех архитектур, а не только x86) действительно имеют микс. Это уменьшает общий объем проделанной работы, выполняемой при размножении / восстановлении в вызываемых и вызываемых абонентах.

Заставляя вызывающего абонента разливать / перезагружать все вокруг каждого вызова функции не подходит для размера кода или производительности. Сохранение / восстановление некоторых сохраняемых вызовов regs в начале / конце функции позволяет не-листовым функциям сохранять некоторые вещи в регистре через call s.

Рассмотрим некоторый код, который вычисляет пару вещей, а затем cout << "result: " << a << "foo" << b*c << '\n'; Это 4 вызова функций std::ostream operator<<, и они обычно не встроены. Сохранение адреса cout и местных жителей, которые вы просто вычислили в энергонезависимых регистрах, означает, что вам нужны только некоторые дешевые mov reg,reg инструкции для настройки аргументов для следующего вызова. (Или push в соглашении о вызове stack-args).

Но наличие некоторых регистров, сбрасываемых вызовом, которые могут использоваться без сохранения, также очень важно. Функции, которым не нужны все архитектурные регистры, могут просто использовать регистры с затухающими вызовами как временные. Это позволяет избежать разлива / перезагрузки в критический путь для цепочек зависимостей вызывающего абонента (для очень маленьких абонентов), а также для сохранения инструкций.

Иногда сложная функция будет сохранять / восстанавливать некоторые регистры с сохранением вызовов только чтобы получить больше полных регистров (например, вы видите XMM для хрустания числа). Это вообще стоит того; сохранение / восстановление энергонезависимых регистров вызывающего абонента обычно лучше, чем проливание / перезагрузка собственных локальных переменных в стек, особенно если вы не должны делать это внутри любого цикла.


Еще одна причина для регистры с затухающими звонками - это то, что обычно некоторые из ваших значений «мертвы» после вызова функции: вам нужны только их как аргументы функции. Вычисление их в списках, записанных с помощью call-clobbered, означает, что вам не нужно сохранять / восстанавливать что-либо, чтобы освободить эти регистры, но также и то, что ваш собеседник также может свободно их использовать. Это еще лучше при вызове соглашений, которые передают args в регистры: вы можете вычислять свои входы непосредственно в регистры, проходящие через arg. (И скопируйте все в защищенные вызовом регистры или проливайте их на стеке памяти, если они вам также понадобятся после этой функции.)

(Мне нравятся термины, сохраненные по вызову, по сравнению с call-clobbered, спасенный или спасенный. Последние термины подразумевают, что кто-то должен сохранять регистры вместо того, чтобы просто позволить мертвым значениям умереть. volatile / non-volatile не плохо, но эти термины также имеют другие технические значения как ключевые слова C или в терминах вспышки против DRAM.)

13
задан Old Pro 24 January 2019 в 06:55
поделиться

4 ответа

Could you try this?

ORDER BY ISNULL(no),no;
32
ответ дан 1 December 2019 в 18:06
поделиться

You can use a CASE statement to tweak ordering:

SELECT * 
FROM table 
ORDER BY case when no is null then 2 else 1 end, no

This orders on "nullableness" first, and no second.

4
ответ дан 1 December 2019 в 18:06
поделиться

Ok, I think I got it:

SELECT * FROM table WHERE no IS NOT NULL ORDER BY no ASC UNION
SELECT * FROM table WHERE no IS NULL

Or is there any better way ?

1
ответ дан 1 December 2019 в 18:06
поделиться
SELECT * FROM table ORDER BY COALESCE(no,999999) ASC

Just replace the 999999 with something larger if your numbers are naturally bigger than that.

2
ответ дан 1 December 2019 в 18:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: