Re[7]: string_view по ссылке или по значению
От: watchmaker  
Дата: 28.05.19 08:29
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Вот пример:

TB>
TB>#include <cstdio>

TB>struct string_view {
TB>  const char* chars;
TB>  size_t length;
TB>};

TB>extern"C" void print(struct string_view sv) {
TB>  for (size_t i=0; i<sv.length; ++i) {
TB>    printf("%c", sv.chars[i]);
TB>  }
TB>};


TB>clang hello.cpp -o hello.ll -S -emit-llvm -O3


И? Заменяем теперь сигнатуру функции на void print(const string_view& sv) и видим, что в IR лучше не стало.
То есть с точки зрения IR кода тут нет выгоды, если мы будет передавать по ссылке const string_view& sv.

А вообще на IR тут смотреть плохо. Он не показывает важные машинно-специфичные оптимизации. Например, передача по ссылке или по значению влияет на register pressure, но в IR это никак не отображено — в нём же бесконечное количество регистров
Re[8]: string_view по ссылке или по значению
От: T4r4sB Россия  
Дата: 28.05.19 08:42
Оценка:
Здравствуйте, watchmaker, Вы писали:

W>И? Заменяем теперь сигнатуру функции на void print(const string_view& sv) и видим, что в IR лучше не стало.


Вот именно! IR никак не меняется от замены указателя на значение!

W>А вообще на IR тут смотреть плохо. Он не показывает важные машинно-специфичные оптимизации. Например, передача по ссылке или по значению влияет на register pressure, но в IR это никак не отображено — в нём же бесконечное количество регистров


Неважно, он показывает, что в функцию передаётся именно указатель. По-моему, этого достаточно.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[9]: string_view по ссылке или по значению
От: watchmaker  
Дата: 28.05.19 08:48
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Здравствуйте, watchmaker, Вы писали:


W>>И? Заменяем теперь сигнатуру функции на void print(const string_view& sv) и видим, что в IR лучше не стало. :))


TB>Вот именно! IR никак не меняется от замены указателя на значение!


Хорошо что мы в этом согласны :)

Значит эта ветка всё же показывает, что тут нет веских причин передавать string_view по ссылке даже под win. Так?
Напомню, с чего всё началось: http://rsdn.org/forum/cpp/7455853.1
Автор: T4r4sB
Дата: 28.05.19
:)

W>>Если нет веских причин передавать по ссылке, то передавать string_view всегда нужно по значению.
TB>Убогое АБИ — веская причина?

Re[9]: string_view по ссылке или по значению
От: reversecode google
Дата: 28.05.19 08:55
Оценка:
TB>Неважно, он показывает, что в функцию передаётся именно указатель. По-моему, этого достаточно.

в результирующем асм коде никакого указателя нет даже в вашем случае
компилятор оптимизирует и передает в двух регистрах вашу пару хранящуюся в структуре
Re[10]: string_view по ссылке или по значению
От: T4r4sB Россия  
Дата: 28.05.19 09:34
Оценка:
Здравствуйте, watchmaker, Вы писали:


W>Значит эта ветка всё же показывает, что тут нет веских причин передавать string_view по ссылке даже под win. Так?

W>Напомню, с чего всё началось: http://rsdn.org/forum/cpp/7455853.1
Автор: T4r4sB
Дата: 28.05.19

W>

W>>>Если нет веских причин передавать по ссылке, то передавать string_view всегда нужно по значению.
TB>>Убогое АБИ — веская причина?


Ну как сказать. Убогое АБИ — это веская причина того, что ты в принципе не сможешь передать св по значению. Согласен?
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[10]: string_view по ссылке или по значению
От: T4r4sB Россия  
Дата: 28.05.19 09:36
Оценка:
Здравствуйте, reversecode, Вы писали:

R>в результирующем асм коде никакого указателя нет даже в вашем случае

R>компилятор оптимизирует и передает в двух регистрах вашу пару хранящуюся в структуре

Компилятор передаёт указатель на структуру снаружи и разыменовывает её внутри. Не, я понимаю, есть оптимизации между границами функций (тогда вообще пофиг как передавать, компилятор разберётся), но если функция сидит в другом бинарнике, например, то эта оптимизация не сработает.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[11]: string_view по ссылке или по значению
От: reversecode google
Дата: 28.05.19 09:41
Оценка:
TB>Компилятор передаёт указатель на структуру снаружи и разыменовывает её внутри. Не, я понимаю, есть оптимизации между границами функций (тогда вообще пофиг как передавать, компилятор разберётся), но если функция сидит в другом бинарнике, например, то эта оптимизация не сработает.

вам надо посмотреть видео доклада антона полухина про С++ строки, и вывод именно такой — не надо быть умнее компилятора

не важно где функция, компилятор увидит передающийся тип и как он используется в теле
и с оптимизирует
Re: string_view по ссылке или по значению
От: fk0 Россия https://fk0.name
Дата: 28.05.19 10:34
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>В теории по ссылке эффективнее т.к. передача всего одного указателя вместо двух.

_NN>В интернетах пишут, что незачем заморачиваться класс и так маленький и по значению сойдёт.
_NN>Что думаете ?

При передаче по значению его можно модифицировать внутри функции, а не копировать (если по константной ссылке).
Re[10]: string_view по ссылке или по значению
От: watchmaker  
Дата: 28.05.19 10:55
Оценка:
Здравствуйте, reversecode, Вы писали:


TB>>Неважно, он показывает, что в функцию передаётся именно указатель. По-моему, этого достаточно.


R>в результирующем асм коде никакого указателя нет даже в вашем случае

R>компилятор оптимизирует и передает в двух регистрах вашу пару хранящуюся в структуре
Под какую платформу? В этой ветке T4r4sB рассказывает про windows.
А windows ABI это явно запрещает:

A single argument is never spread across multiple register

https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=vs-2019
Re[2]: string_view по ссылке или по значению
От: _NN_ www.nemerleweb.com
Дата: 28.05.19 11:02
Оценка:
А что насчёт constexpr ?

#include <string_view>

constexpr bool a(std::string_view const& l, std::string_view const& r) {
    return true;
}

// OK
void f() {
    std::string_view q("A");
    std::string_view w("A");
    constexpr bool xx = a(q, w);
}

constexpr bool b(std::string_view  l, std::string_view  r) {
    return true;
}

// А тут не собирается
void g() {
    std::string_view q("A");
    std::string_view w("A");
    constexpr bool xx = b(q, w);
}
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[11]: string_view по ссылке или по значению
От: watchmaker  
Дата: 28.05.19 11:07
Оценка: +1
Здравствуйте, T4r4sB, Вы писали:

TB>Ну как сказать. Убогое АБИ — это веская причина того, что ты в принципе не сможешь передать св по значению. Согласен?


Вот прямо с такой формулировкой? Совсем не согласен!
Возможность передать по значению — это свойство языка C++. От используемого ABI оно не зависит. Даже если используется абстрактная машина C++ и никакого ABI нет вообще.

Вот я передал long double по значению:
extern void foo(long double);
foo(4);


А вот я передал по значению std::string_view:
extern void bar(std::string_view);
bar("hello"sv);


Этот код будет передавать аргументы вне зависимости от ABI.

ABI будет задавать лишь куда аргументы будет помещены: например, будут ли они переданы через регистры или переданы через стек, или каким-то ещё невообразимым образом. Но во всех случаях они будут переданы по значению. "Через регистры по значению", "через стек по значению", "невообразимым образом, но по значению", и так далее.
Re[12]: string_view по ссылке или по значению
От: T4r4sB Россия  
Дата: 28.05.19 11:14
Оценка: +2
Здравствуйте, watchmaker, Вы писали:

W>Вот прямо с такой формулировкой? Совсем не согласен!

W>Возможность передать по значению — это свойство языка C++. От используемого ABI оно не зависит. Даже если используется абстрактная машина C++ и никакого ABI нет вообще.

В контексте низкоуровневых оптимизаций говорить об абстракциях неуместно.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[12]: string_view по ссылке или по значению
От: _NN_ www.nemerleweb.com
Дата: 28.05.19 11:32
Оценка:
Здравствуйте, watchmaker, Вы писали:

W>ABI будет задавать лишь куда аргументы будет помещены: например, будут ли они переданы через регистры или переданы через стек, или каким-то ещё невообразимым образом. Но во всех случаях они будут переданы по значению. "Через регистры по значению", "через стек по значению", "невообразимым образом, но по значению", и так далее.

Мы тут обсуждаем именно подкапотную работу, а не абстракции языка.
То, что всё передается по значению по умолчанию это свойства языка и никто с этим не спорит, вопрос будет ли это достаточно эффективным в случае string_view или нет.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[13]: string_view по ссылке или по значению
От: watchmaker  
Дата: 28.05.19 11:35
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Здравствуйте, watchmaker, Вы писали:


W>>Вот прямо с такой формулировкой? Совсем не согласен!

W>>Возможность передать по значению — это свойство языка C++. От используемого ABI оно не зависит. Даже если используется абстрактная машина C++ и никакого ABI нет вообще.

TB>В контексте низкоуровневых оптимизаций говорить об абстракциях неуместно.


И это говорит человек, который не спускается ниже IR при разговорах об оптимизации!

Ладно, если серьёзно, то вопрос в первом сообщении темы был про передачу аргументов std::string_view: по ссылке это делать или по значению.

Понятно, что есть кривые ABI, где не будет разницы в сгенированном машинном коде при вызове функции. Спасибо, что напомнил об этом (я вот под windows давно не пишу и честно об этом забыл). Но это лишь означает, что их наличие не сдвигает чашу весов в сторону одного из вариантов. То есть их наличие — не причина предпочитать const std::string_view против const std::string_view& или наоборот.
А вот то, что при const std::string_view компилятору разрешено сделать больше оптимизаций, чем при const std::string_view& (даже на архитектурах, где передача идёт через память, а код вызова одинаков с точностью до интструкции), — уже причина.
И то, что на systemV ABI передача через значение чаще эффективнее — тоже причина (хотя не такая хорошая, как предыдущая).
Re[4]: string_view по ссылке или по значению
От: _NN_ www.nemerleweb.com
Дата: 28.05.19 11:37
Оценка:
Здравствуйте, Zhendos, Вы писали:

Z>Разве не очевидно какой вариант быстрее?


Вот выхлоп MSVC.
Как видно передача по значению занимается копированием, а по ссылке нет.
Неужели вариант с копированием будет быстрее ?

struct view { char const*p; int size; }

view f(view) PROC                         ; f
        movups  xmm0, XMMWORD PTR [rdx]
        mov     rax, rcx
        movups  XMMWORD PTR [rcx], xmm0
        ret     0
view f(view) ENDP                         ; f

v$ = 8
view const & g(view const &) PROC                     ; g
        mov     rax, rcx
        ret     0
view const & g(view const &) ENDP                     ; g
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: string_view по ссылке или по значению
От: watchmaker  
Дата: 28.05.19 11:39
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>А что насчёт constexpr ?

А что?
C constexpr всё хорошо. Это с приведённым кодом не очень.


_NN>// А тут не собирается


Да. А ещё интересно, что даже если заменить std::string_view, скажем, на int или на void*, то всё равно не собирается:
constexpr bool b(void*  l, void*  r) {
    return true;
}

void g() {
    void* q = nullptr;
    void* w = nullptr;
    constexpr bool xx = b(q, w);
}


Наверное, дело тут ошибка всё же не в std::string_view
Re[11]: string_view по ссылке или по значению
От: reversecode google
Дата: 28.05.19 11:57
Оценка:
https://godbolt.org/z/uEKEED
под виндовс какой именно компиль ?
кстати по линку выше видно что если передавать по ссылке
то происходит два дополнительных чтения с памяти в цикле
так то всяко разно передача по значению будет быстрей
Re[4]: string_view по ссылке или по значению
От: _NN_ www.nemerleweb.com
Дата: 28.05.19 12:09
Оценка:
Здравствуйте, watchmaker, Вы писали:

W>Да. А ещё интересно, что даже если заменить std::string_view, скажем, на int или на void*, то всё равно не собирается:

W>Наверное, дело тут ошибка всё же не в std::string_view

Что значит ошибка в коде ?
Код компилируется с ссылкой успешно, значит в нём нет ошибки.

Добавляем ссылку и код собирается без проблем:
constexpr bool b(void*&  l, void*&  r) {
    return true;
}

void g() {
    void* q = nullptr;
    void* w = nullptr;
    constexpr bool xx = b(q, w);
}

https://gcc.godbolt.org/z/IBhF8A
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[12]: string_view по ссылке или по значению
От: watchmaker  
Дата: 28.05.19 12:39
Оценка:
Здравствуйте, reversecode, Вы писали:

R>https://godbolt.org/z/uEKEED

R>под виндовс какой именно компиль ?
Ну msvc вроде не умеет там под что-то отличное копмилировать, так что он подойдёт. А clang и gcc там собирают под unix, но для экспериментов их можно попросить использовать чужеродное abi.

R>кстати по линку выше видно что если передавать по ссылке

R>то происходит два дополнительных чтения с памяти в цикле
R>так то всяко разно передача по значению будет быстрей
Всё так.
И это платформонезависимая оптимизация. То есть для её не важно какое abi используется, и вообще linux ли там или windows. Сама её возможность следует из описания абстрактной машины C++.
Ведь если std::string_view передаётся по ссылке, то компилятор будет обязан на каждой итерации перечитывать значение sv.size() из памяти. Например, из-за того, что передача по ссылке не запрещает ссылаться для обоих аргументов функции на одну и ту же память (а значит модификация sum может поменять значение str.size(), а следовательно нужно перечитать str).
Строго говоря, конечно, компилятор может сгенерировать две ветки в функции: в одной делать честно и тупо, а в другой проверять, что все аргументы не пересекаются по памяти и сводить его к случаю как будто аргумент передан по значению. Но для мало-мальски сложных функций это очень сложно сделать на практике (например, сложно доказать, что какой-нибудь callback не поменяет память в string_view, ссылка на которую была передана в функцию).
То есть тут передача по значению играет роль модификатора restrict из C: она гарантирует, что аргументы ссылаются на разную память, и из-за этого её можно эффективно кешировать и отслеживать изменения в ней.
Re[5]: string_view по ссылке или по значению
От: Zhendos  
Дата: 28.05.19 13:20
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Здравствуйте, Zhendos, Вы писали:


Z>>Разве не очевидно какой вариант быстрее?


_NN>Вот выхлоп MSVC.

_NN>Как видно передача по значению занимается копированием, а по ссылке нет.
_NN>Неужели вариант с копированием будет быстрее ?

Вы куда-то контекст обсуждения потеряли.
Естественно функция которую не вызывают вообще самая быстрая,
можно считать что она вызывается за 0 тактов.
Но мы же хотим чтобы в вся программа при использовании того или иного
способа возврата string_view работала быстрее.
Поэтому нужно рассматривать функцию возвращающую string_view вместе
с кодом который ее вызывает.

И я вижу два варианта:

string_view_ref_or_value get_string_view();

string_view_ref_or_value x = get_string_view();


либо мы сразу используем x, тогда мы лезем в память и достаем
и data и size (1), или передаем полученный x куда-то, но как мы выяснили
передачу лучше делать по значению, значит мы снова лезем в память и опять же достаем
data и size (2) (можно конечно дальше передавать ссылку, что кстати очень опасно,
но в конце концов мы придем к 1 или 2).

В обоих случаях получается что либо одинаково быстро будет
работать вся программа или чуть медленнее, если string_view вычисляется,
потому кладется в поле класса, а потом на поле класса возвращается ссылка.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.