Re[2]: Как вышло, что наложение предполагается по умолчанию?
От: AndrewJD США  
Дата: 15.09.21 15:49
Оценка: +2
Здравствуйте, rg45, Вы писали:

R>Корректность программы всегда была выше по приоритету, чем производительность. А как иначе?


Да ладно, если бы это было так небыло бы баек про форматирование диска при доступе к нулевому указателю.
"For every complex problem, there is a solution that is simple, neat,
and wrong."
Re[4]: Как вышло, что наложение предполагается по умолчанию?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 15.09.21 17:12
Оценка:
Здравствуйте, B0FEE664, Вы писали:

ЕМ>>Придумали же давным-давно volatile, хотя могли бы объявить: раз какие-то переменные могут меняться извне текущего потока, то и никаких вам регистровых оптимизаций, только память.

BFE>Ага. А теперь volatile — deprecated. volatile имеет смысл только на однопроцессорной одноядерной архитектуре (что было давным давно), во всех остальных случаях это непонятно как работающая и что означающая конструкция.

Загляните например сюда. Все эти READ_ONCE, которые говорят "это чтение не кэшировать", сделаны внутри через volatile-указатель.

Да, оно не отменяет необходимость в явных барьерах. Но оно удобнее, чем делать какой-нибудь atomic_signal_fence на каждом углу, и эффективнее (действует точечно).
The God is real, unless declared integer.
Re[2]: Как вышло, что наложение предполагается по умолчанию?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 15.09.21 17:20
Оценка: +1
Здравствуйте, watchmaker, Вы писали:

W>Если бы можно было переделать С++ с нуля, то в него можно было бы добавить десяток quality-of-life улучшений, которые бы не изменили принципиально язык, но немедленно бы сделали его более быстрым, простым и надёжным. Сюда не только вошли бы более разумные правила на aliasing, но и такие вещи как move для всех типов по умолчанию, менее безумные правила octal-literals (когда одна цифра в числе меняет систему счисления), быстрые строки (с длиной, а не null-terminated), отсутствие неявных преобразований (как литеральный 0 в указатель) и т.п.


Это всё как раз можно и сейчас без коренной ломки, банальными мерами нужна только воля стандартизаторов. Типа так: шаг 1 — вводится поддержка "#pragma STDC good_octal on" в стандарт. Шаг 2 — основные компиляторы это сделали. Шаг 3 — вводится правило в стандарты типа MISRA. Лет 10 на полный цикл, да. Но — возможно.
Аналогично прагмами или [[контекстными пометками]] можно задать правила арифметики, алиасинга, работы с пустыми указателями, усиление типизации, и прочая и прочая.
Кстати, "быстрые строки" в виде "qwerty"sv есть в C++17.

А вот переделать синтаксис, чтобы было не int (*foo)(int), вот это уже сложнее — поддерживать десятилетями оба синтаксиса впараллель — легче таки новый язык создать.

W>2. Если делать правильно и переделать всё кардинально, то потеряется совместимость с предыдущим кодом, и такой язык сильно потеряет в привлекательности — кому нужен язык, если нельзя использовать многочисленные наработки, а нужно всё переписывать под него заново? Нужно очень сильно вложится, чтобы сделать такой язык популярным.


Ну вот всё что ты предлагаешь — не ломает прямую совместимость. Обратную ломает, но она и так ломается с каждым новым стандартом, поэтому не страшно.
The God is real, unless declared integer.
Re[2]: Как вышло, что наложение предполагается по умолчанию?
От: T4r4sB Россия  
Дата: 15.09.21 18:01
Оценка: :)
Здравствуйте, watchmaker, Вы писали:


W>Если бы можно было переделать С++ с нуля, то в него можно было бы добавить десяток quality-of-life улучшений, которые бы не изменили принципиально язык, но немедленно бы сделали его более быстрым, простым и надёжным. Сюда не только вошли бы более разумные правила на aliasing, но и такие вещи как move для всех типов по умолчанию, менее безумные правила octal-literals (когда одна цифра в числе меняет систему счисления), быстрые строки (с длиной, а не null-terminated), отсутствие неявных преобразований (как литеральный 0 в указатель) и т.п.


А ещё борроу-чекер, пугающий синтаксис с Vec::<String>, упоротые правила мутабельных ссылок, вычисление типа переменной в обе стороны и ну ты понял, на кого я намекаю. И знаешь, это тоже по итогу весьма спорно и не всегда очевидно, помогает вся эта фигня или мешает
Re[3]: Как вышло, что наложение предполагается по умолчанию?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 15.09.21 19:00
Оценка:
Здравствуйте, netch80, Вы писали:

N>Это всё как раз можно и сейчас без коренной ломки, банальными мерами нужна только воля стандартизаторов.


У меня уже давно стойкое впечатление, что среди стандартизаторов преобладают сторонники понимания сути программирования, как процесса подбора освященных стандартом и мэтрами конструкций, в результате чего на выходе программы получается требуемый результат. При таком подходе от программиста не требуется понимания того, что именно будет делать железо по его программе — достаточно лишь, чтобы результат получался верным. Сторонники сохранения преемственности с Си из комитета постепенно вымываются (или выживаются).

Так что нет особых оснований ожидать от языка подвижек в сторону удобства программирования, близкого к железу. Язык движется в сторону какого-нибудь Fortran-77, Algol-68 и подобного.
Re[3]: Как вышло, что наложение предполагается по умолчанию?
От: rg45 СССР  
Дата: 15.09.21 19:42
Оценка:
Здравствуйте, AndrewJD, Вы писали:

R>Корректность программы всегда была выше по приоритету, чем производительность. А как иначе?


AJD>Да ладно, если бы это было так небыло бы баек про форматирование диска при доступе к нулевому указателю.


Да но при этом четко сказано что доступ к памяти по нулевому указателю порождает неопределенное поведение. И если пользователь это делает, то он ССЗБ. Тогда как в рассматриваемом случае ответственность за корректность работы программы полностью лежит на компиляторе.

Ну то есть, я имел в виду корректность лишь в зоне ответственности компилятора, которая достаточно четко очерчена.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 15.09.2021 20:40 rg45 . Предыдущая версия . Еще …
Отредактировано 15.09.2021 20:25 rg45 . Предыдущая версия .
Re[7]: Как вышло, что наложение предполагается по умолчанию?
От: B0FEE664  
Дата: 16.09.21 08:21
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

BFE>>Для volatile нет гарантий атомарности.

ЕМ>А я что-то говорил за атомарность?

В том-то и дело, что нет.
И каждый день — без права на ошибку...
Re[5]: Как вышло, что наложение предполагается по умолчанию?
От: B0FEE664  
Дата: 16.09.21 08:48
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

BFE>>если программист забыл отменить предположение об отмене наложения и получил очень странную, практически неуловимую ошибку, то его сразу призвать к ответу?

ЕМ>Если перечислять ситуации, в которых программист что-то забыл, и получил странную ошибку, то мы очень быстро устанем.
Если последовательно применять best practice, то никаких странных ошибок не возникает.

ЕМ>А еще может быть, что программист явно указал отсутствие наложение, а через месяц или год изменил алгоритм так, что наложение возникло, но квалификатор убрать забыл. На все такие варианты соломы не напасешься.

Это почему же нет? Нет квалификатора — нет проблемы.

BFE>>Правильно ли я понимаю, что под словом "некоторых" скрываются все стандартные алгоритмы из <algorithm>?

ЕМ>Положим, не все, но многие, да. Но много их лишь внутри <algorithm>, а в типичной программе — очень мало.
В типичной программе всё очень похоже на функции из algorithm.

BFE>>volatile имеет смысл только на однопроцессорной одноядерной архитектуре

ЕМ>Э-э-э... Когда железо меняет значение регистра в произвольные моменты времени — как это связано с количеством процессов/ядер, работающих с этим железом?
Вот, допустим, программа читает 32-х битное значение в переменную из регистра, прочитала первые два байта и тут железо меняет значение регистра, поэтому прочтение третьего и четвёртого байта будут взяты от уже изменённого значения. Всё ведь так и задумано? Да?
И каждый день — без права на ошибку...
Re[8]: Как вышло, что наложение предполагается по умолчанию?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 16.09.21 09:02
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>>>Для volatile нет гарантий атомарности.

ЕМ>>А я что-то говорил за атомарность?

BFE>В том-то и дело, что нет.


Тогда в чем проблема? Атомарность требуется не всегда. Например, если потоку нужно сообщить другим потокам, что произошло некое событие (а не будить их из спячки), нередко достаточно просто установить значение переменной, снабдив ее volatile для надежного считывания из памяти. Или, когда один поток формирует даннне, а другой по таймеру отображает их в GUI, атомарность требуется только для связанных значений. Отдельные достаточно просто класть в память, а volatile указывается, чтобы операции считывания не выносились из цикла.
Re[6]: Как вышло, что наложение предполагается по умолчанию?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 16.09.21 09:30
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Вот, допустим, программа читает 32-х битное значение в переменную из регистра, прочитала первые два байта и тут железо меняет значение регистра, поэтому прочтение третьего и четвёртого байта будут взяты от уже изменённого значения.


Какая здесь связь с многопроцессорностью/многоядерностью? Такое возможно даже на 8-разрядных архитектурах, если флаги в регистрах выставляются асинхронно. Для борьбы с этим есть ряд способов, которые Вам должны быть известны.
Re[9]: Как вышло, что наложение предполагается по умолчанию?
От: B0FEE664  
Дата: 16.09.21 09:48
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

BFE>>>>Для volatile нет гарантий атомарности.

ЕМ>>>А я что-то говорил за атомарность?
BFE>>В том-то и дело, что нет.

ЕМ>Тогда в чем проблема? Атомарность требуется не всегда. Например, если потоку нужно сообщить другим потокам, что произошло некое событие (а не будить их из спячки), нередко достаточно просто установить значение переменной, снабдив ее volatile для надежного считывания из памяти. Или, когда один поток формирует даннне, а другой по таймеру отображает их в GUI, атомарность требуется только для связанных значений. Отдельные достаточно просто класть в память, а volatile указывается, чтобы операции считывания не выносились из цикла.


Так как нет гарантий, что операции чтения атомарны (даже для одного байта) и если "один поток формирует даннне, а другой по таймеру отображает их в GUI", то нет гарантий, что отображаемые данные в GUI отображают реальные значения. Более того, как вы понимаете, если есть два значения и операции над ними атомарны, тогда при отображении эти значений в GUI нет никаких гарантий их согласованности. Скажем строка принимающая два значения "OK" или "КО" в GUI может отобразится как "OO", "OK", "KO" или "KK". Т.е. нет никакого смысла передавать более одного данного из потока в поток таким способом.
И каждый день — без права на ошибку...
Re[7]: Как вышло, что наложение предполагается по умолчанию?
От: B0FEE664  
Дата: 16.09.21 10:03
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

BFE>>Вот, допустим, программа читает 32-х битное значение в переменную из регистра, прочитала первые два байта и тут железо меняет значение регистра, поэтому прочтение третьего и четвёртого байта будут взяты от уже изменённого значения.


ЕМ>Какая здесь связь с многопроцессорностью/многоядерностью?

Изначально речь шла про память, а не про регистры.

ЕМ>Такое возможно даже на 8-разрядных архитектурах, если флаги в регистрах выставляются асинхронно. Для борьбы с этим есть ряд способов, которые Вам должны быть известны.

Насколько мне известно, на всех архитектурах все мне известные способы сводятся ровно к одному — к разнесению по времени операций чтения и записи. А чем это в сути своей отличается от однопроцессорности?
И каждый день — без права на ошибку...
Re[10]: Как вышло, что наложение предполагается по умолчанию?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 16.09.21 13:22
Оценка: :)
Здравствуйте, B0FEE664, Вы писали:

BFE>Так как нет гарантий, что операции чтения атомарны (даже для одного байта)


Где их нет? Для большинства конкретных архитектур они как раз есть. А задача сделать надежную программу для абстрактной, заранее неизвестной архитектуры, напоминает анекдот о сферической лошади в вакууме.

BFE>если есть два значения и операции над ними атомарны, тогда при отображении эти значений в GUI нет никаких гарантий их согласованности.


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

BFE>Скажем строка принимающая два значения "OK" или "КО" в GUI может отобразится как "OO", "OK", "KO" или "KK". Т.е. нет никакого смысла передавать более одного данного из потока в поток таким способом.


Может, смысла и нет, а я всю жизнь передаю, и отлично работает, ни разу не жаловались.
Re[8]: Как вышло, что наложение предполагается по умолчанию?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 16.09.21 14:33
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Изначально речь шла про память, а не про регистры.


Чем регистры любого контроллера, отображенные на адресное пространство, отличаются от памяти с точки зрения программы?

ЕМ>>Такое возможно даже на 8-разрядных архитектурах, если флаги в регистрах выставляются асинхронно.

BFE>Насколько мне известно, на всех архитектурах все мне известные способы сводятся ровно к одному — к разнесению по времени операций чтения и записи.

Операции чтения и записи физически не могут быть одновременными — их разносит, как минимум, сама аппаратура. Или о чем Вы?

BFE>А чем это в сути своей отличается от однопроцессорности?


А чем двухпроцессорная система, в которой параллельные потоки обмениваются данными через общую память, отличается от однопроцессорной, где поток обменивается данными с контроллером, фактически представляющим собой независимый процессор?
Re[11]: Как вышло, что наложение предполагается по умолчанию?
От: TailWind  
Дата: 16.09.21 15:36
Оценка:
BFE>>Так как нет гарантий, что операции чтения атомарны (даже для одного байта)

ЕМ>Где их нет? Для большинства конкретных архитектур они как раз есть. А задача сделать надежную программу для абстрактной, заранее неизвестной архитектуры, напоминает анекдот о сферической лошади в вакууме.


Про один байт можете быть совершенно спокойны

Микросхема памяти имеет только один порт. Более того минимальная единица записи — 1 байт

Писать и читать можно только по очереди, а не одновременно
Поэтому никто не сможет изменить часть бит, пока вы читаете
Никак не сможет получится, что вы считали байт, в котором часть бит от нового значения, а часть от старого
Целостность байта нарушить не получится
Re[12]: Как вышло, что наложение предполагается по умолчанию?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 16.09.21 15:48
Оценка:
Здравствуйте, TailWind, Вы писали:

TW>Микросхема памяти имеет только один порт. Более того минимальная единица записи — 1 байт


Какие архитектуры мы обсуждаем? Если сферические в вакууме, то микросхемы памяти бывают и одно-, и четырех-, и восьми-битовыми, и более широкими. А синхронизация чтения/записи определяется не битностью отдельных микросхем, а подаваемым на них синхросигналом. Так что можно построить архитектуру, где чтение и запись осуществляются побитно.

В реальных же архитектурах разрядность памяти стараются делать равной разрядности магистрали. Если читается/пишется не полное слово, то на магистрали указывается, какие части будут участвовать, а какие нет (обычно это делается на уровне байтов, но так просто удобнее — можно управлять группами любой разрядности).

TW>Поэтому никто не сможет изменить часть бит, пока вы читаете


Если сделать архитектуру с побитной адресацией — легко. А на нормальных современных всегда гарантируется атомарность чтения/записи в пределах ширины магистрали (общей или процессора, если его магистраль Уже магистрали памяти).
Re[13]: Как вышло, что наложение предполагается по умолчанию?
От: TailWind  
Дата: 16.09.21 16:41
Оценка:
ЕМ>В реальных же архитектурах разрядность памяти стараются делать равной разрядности магистрали. Если читается/пишется не полное слово, то на магистрали указывается, какие части будут участвовать, а какие нет (обычно это делается на уровне байтов, но так просто удобнее — можно управлять группами любой разрядности).

Не в разрядности дело
У нас адрес может указывать только на байт.
Поэтому битовые операции невозможны на аппаратном уровне
Re[14]: Как вышло, что наложение предполагается по умолчанию?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 16.09.21 18:08
Оценка: +1
Здравствуйте, TailWind, Вы писали:

TW>У нас адрес может указывать только на байт.


Тогда к чему все это пережевывание? На реальной архитектуре байт по определению атомарен. Поля, выровненные по ширине магистрали, тоже атомарны. О чем спич?
Re[4]: Как вышло, что наложение предполагается по умолчанию?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 17.09.21 06:52
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>У меня уже давно стойкое впечатление, что среди стандартизаторов преобладают сторонники понимания сути программирования, как процесса подбора освященных стандартом и мэтрами конструкций, в результате чего на выходе программы получается требуемый результат. При таком подходе от программиста не требуется понимания того, что именно будет делать железо по его программе — достаточно лишь, чтобы результат получался верным. Сторонники сохранения преемственности с Си из комитета постепенно вымываются (или выживаются).


Ну в общем-то именно так, и это неизбежное логичное развитие в современном мире.
Задачи "вывести 1 в порт" стали 0.001% от всех задач. Основные это таки что-то очень высокоуровневое.

Но это таки не мешает тому, что я предлагаю.

ЕМ>Так что нет особых оснований ожидать от языка подвижек в сторону удобства программирования, близкого к железу.


Для этого таки есть разнообразный комплекст средств, которые можно подключать для поддержания правил работы с железом — ну как минимум атомики и барьеры.

Но, да, даже attribute((packed)) пока не стандартизировали. В отличие даже от C#, где StructLayout в стандарте и позволяет сказать про точность до байтика.

А я хотел бы от этих средств даже больше — например, сказать

[[packed, bigendian]]
struct iphdr
  {
    unsigned int version:4;
    unsigned int ihl:4;
    uint8_t tos;
    uint16_t tot_len;
    uint16_t id;
    unsigned reserved:1;
    unsigned dont_fragment:1;
    unsigned more_fragments:1;
    unsigned frag_off:13;
    uint8_t ttl;
    uint8_t protocol;
    uint16_t check;
    uint32_t saddr;
    uint32_t daddr;
    /*The options start here. */
  };


и чтобы указание bigendian работало, как положено, на то, что version будет в старших битах байта по смещению 0, а не младших, как сработает автоматом на x86.
The God is real, unless declared integer.
Отредактировано 17.09.2021 6:58 netch80 . Предыдущая версия .
Re[5]: Как вышло, что наложение предполагается по умолчанию?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 17.09.21 09:23
Оценка:
Здравствуйте, netch80, Вы писали:

N>Задачи "вывести 1 в порт" стали 0.001% от всех задач. Основные это таки что-то очень высокоуровневое.


Да не в портах дело. Чем отличается типичный физик или инженер от типичного математика? У физика и инженера хорошо развито чувство адекватности, сообразности. Если установка, которую предполагается использовать мобильно, получается весом под сто тонн — у них автоматически срабатывает триггер, что это абсурдно. А у математика такого триггера нет: задача решена, и ладно.

Вот у меня телефон 2016-го года на Qualcomm Snapdragon 650. Шесть ядер в среднем по полтора гигагерца. Google Services на нем изначально работали достаточно быстро. А сейчас, когда я тапаю на Update All в списке обновлений, проходит семь-восемь секунд до того, как кнопка Update All превратится в Cancel All. Все это время экран сохраняет прежний вид, и я даже не знаю, сработал мой тап, или нет. Восемь секунд, Карл! На полутора гигагерцах и шести ядрах! Что нужно курить, чтобы так сделать? Я не знаю. Это возможно лишь путем "последовательной записи конструкций языка, в итоге приводящих к решению поставленной задачи". Программированием в его исходном понимании это назвать невозможно.

N>и чтобы указание bigendian работало, как положено, на то, что version будет в старших битах байта по смещению 0


Хм, а какой в этом может быть смысл? Где такое может пригодиться?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.