new vs. malloc
От: _NN_ www.nemerleweb.com
Дата: 23.04.18 21:58
Оценка:
В MSVC malloc определяется так (пропуская несущественную часть):

__declspec(restrict) void * __cdecl malloc(_In_ size_t _Size);


Однако operator new определён без __declspec(restrict).
Из-за этого компилятор может произвести оптимизацию в случае использования malloc, но не может с new.
Можно проверить через флаг /Qvec-report:2

Кто знает, почему стандарт не требует возвращать указатель на не перекрывающиеся данные в 'new' в отличии от malloc ?

P.S.
Если вручную определить в своём проекте new, то можем получить существенное ускорение:
__declspec(restrict) void* operator new(size_t n)
{
    return malloc(n);
}
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: new vs. malloc
От: niXman Ниоткуда https://github.com/niXman
Дата: 24.04.18 05:42
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Кто знает, почему стандарт не требует возвращать указатель на не перекрывающиеся данные в 'new' в отличии от malloc ?


возможно потому, что new можно перегрузить так, чтоб он возвращал что угодно, а не только уникальный адрес...
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[2]: new vs. malloc
От: σ  
Дата: 24.04.18 05:56
Оценка: 22 (1)
Здравствуйте, niXman, Вы писали:

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


_NN>>Кто знает, почему стандарт не требует возвращать указатель на не перекрывающиеся данные в 'new' в отличии от malloc ?


X>возможно потому, что new можно перегрузить так, чтоб он возвращал что угодно, а не только уникальный адрес...


Низя
http://eel.is/c++draft/basic.stc.dynamic.allocation#2.sentence-6 :
> If the request succeeds, the value returned by a replaceable allocation function is a non-null pointer value ([conv.ptr]) p0 different from any previously returned value p1, unless that value p1 was subsequently passed to a replaceable deallocation function.

При этом
http://eel.is/c++draft/basic.stc.dynamic.allocation#2.sentence-7 :
> Furthermore, for the library allocation functions in [new.delete.single] and [new.delete.array], p0 represents the address of a block of storage disjoint from the storage for any other object accessible to the caller.

Т.е. НЕ-library функции могут возвращать, например, указатель на элемент видимого всем глобального массива.
Отредактировано 24.04.2018 6:18 σ . Предыдущая версия . Еще …
Отредактировано 24.04.2018 5:56 σ . Предыдущая версия .
Re[3]: new vs. malloc
От: _NN_ www.nemerleweb.com
Дата: 24.04.18 06:11
Оценка:
Здравствуйте, σ, Вы писали:

σ>При этом

σ>http://eel.is/c++draft/basic.stc.dynamic.allocation#2.sentence-7 :
>> Furthermore, for the library allocation functions in [new.delete.single] and [new.delete.array], p0 represents the address of a block of storage disjoint from the storage for any other object accessible to the caller.

σ>Т.е. НЕ-library функции могут возвращать, например, указатель на элемент видимого всем глобально массива.

Технически и стандартный new может в реализации также использоваться заранее выделенную область.
Хочется понять из стандарта разрешено ли в перегруженном new вернуть один и тот же адрес без вызова delete.
Лично я не вижу в этом смысла и, возможно, стоило бы указать на это как на неопределённое поведение.

Судя по объяснению placement new, он не попадает под требования выше.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[4]: new vs. malloc
От: σ  
Дата: 24.04.18 06:16
Оценка:
Здравствуйте, _NN_, Вы писали:

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


σ>>При этом

σ>>http://eel.is/c++draft/basic.stc.dynamic.allocation#2.sentence-7 :
>>> Furthermore, for the library allocation functions in [new.delete.single] and [new.delete.array], p0 represents the address of a block of storage disjoint from the storage for any other object accessible to the caller.

σ>>Т.е. НЕ-library функции могут возвращать, например, указатель на элемент видимого всем глобально массива.

_NN>Технически и стандартный new может в реализации также использоваться заранее выделенную область.

Ключевые словосочетания: "accessible to the caller", "видимого всем".

_NN>Хочется понять из стандарта разрешено ли в перегруженном new вернуть один и тот же адрес без вызова delete.


Это же было освещено в моём сообщении
http://eel.is/c++draft/basic.stc.dynamic.allocation#2.sentence-6 :
> If the request succeeds, the value returned by a replaceable allocation function is a non-null pointer value ([conv.ptr]) p0 different from any previously returned value p1, unless that value p1 was subsequently passed to a replaceable deallocation function.
Re: new vs. malloc
От: kov_serg Россия  
Дата: 24.04.18 07:18
Оценка: +1 -1
Здравствуйте, _NN_, Вы писали:

_NN>Если вручную определить в своём проекте new, то можем получить существенное ускорение:

Вы получите существенное ускорение если не будете вообще использовать динамическую память.
Re[5]: new vs. malloc
От: _NN_ www.nemerleweb.com
Дата: 24.04.18 09:25
Оценка:
Здравствуйте, σ, Вы писали:

σ>Это же было освещено в моём сообщении

σ>http://eel.is/c++draft/basic.stc.dynamic.allocation#2.sentence-6 :
>> If the request succeeds, the value returned by a replaceable allocation function is a non-null pointer value ([conv.ptr]) p0 different from any previously returned value p1, unless that value p1 was subsequently passed to a replaceable deallocation function.

Т.е. даже перегруженные new должны возвращать различные адреса неперекрывающихся областей, так ?
Получается нет никаких проблем пометить operator new как __declspec(restrict) и получать векторизацию.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[6]: new vs. malloc
От: nikov США http://www.linkedin.com/in/nikov
Дата: 25.04.18 01:51
Оценка: 22 (1)
Здравствуйте, _NN_, Вы писали:

σ>>Это же было освещено в моём сообщении

σ>>http://eel.is/c++draft/basic.stc.dynamic.allocation#2.sentence-6 :
>>> If the request succeeds, the value returned by a replaceable allocation function is a non-null pointer value ([conv.ptr]) p0 different from any previously returned value p1, unless that value p1 was subsequently passed to a replaceable deallocation function.

_NN>Т.е. даже перегруженные new должны возвращать различные адреса неперекрывающихся областей, так ?

_NN>Получается нет никаких проблем пометить operator new как __declspec(restrict) и получать векторизацию.

То, что указатели, которые возвращаются разными вызовами оператора new, должны быть различны между собой, не означает, что такой указатель не может быть получен каким-либо другим образом. Таким образом, гарантий отсутствия алиасинга нет.
Re[6]: new vs. malloc
От: σ  
Дата: 26.04.18 02:04
Оценка:
Здравствуйте, _NN_, Вы писали:

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


σ>>Это же было освещено в моём сообщении

σ>>http://eel.is/c++draft/basic.stc.dynamic.allocation#2.sentence-6 :
>>> If the request succeeds, the value returned by a replaceable allocation function is a non-null pointer value ([conv.ptr]) p0 different from any previously returned value p1, unless that value p1 was subsequently passed to a replaceable deallocation function.

_NN>Т.е. даже перегруженные new должны возвращать различные адреса неперекрывающихся областей, так ?

_NN>Получается нет никаких проблем пометить operator new как __declspec(restrict) и получать векторизацию.

Не знаю. Стандарт говорит, что
http://eel.is/c++draft/basic.stc.dynamic.allocation#1.sentence-2 :
> The return type shall be void*.

Насколько `__declspec(restrict) void*` это не нарушает, при том, что __declspec(restrict) — это расширение конкретной реализации?
Раз реализация позволяет, то почему бы и нет.
Re[7]: new vs. malloc
От: σ  
Дата: 26.04.18 02:08
Оценка:
Здравствуйте, nikov, Вы писали:

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


σ>>>Это же было освещено в моём сообщении

σ>>>http://eel.is/c++draft/basic.stc.dynamic.allocation#2.sentence-6 :
>>>> If the request succeeds, the value returned by a replaceable allocation function is a non-null pointer value ([conv.ptr]) p0 different from any previously returned value p1, unless that value p1 was subsequently passed to a replaceable deallocation function.

_NN>>Т.е. даже перегруженные new должны возвращать различные адреса неперекрывающихся областей, так ?

_NN>>Получается нет никаких проблем пометить operator new как __declspec(restrict) и получать векторизацию.

N>То, что указатели, которые возвращаются разными вызовами оператора new, должны быть различны между собой, не означает, что такой указатель не может быть получен каким-либо другим образом. Таким образом, гарантий отсутствия алиасинга нет.


ТС вроде хочет сделать свою перегрузку operator new на основе malloc, которая (в его реализации) гарантирует отсутствие алиасинга.
Как понять "гарантий отсутствия алиасинга нет"?
Re: new vs. malloc
От: watchmaker  
Дата: 26.04.18 09:55
Оценка: 21 (2)
Здравствуйте, _NN_, Вы писали:

_NN>Если вручную определить в своём проекте new, то можем получить существенное ускорение

Я согласен, что лучше бы иметь такое свойство изначально, чем не иметь. Но не считаю, что этого достаточно.
В этом примере память используется сразу после выделения malloc'ом или new. Но как часто такая ситуация встречается в программах? Кажется, что обычно память выделяется где-то в одном месте, а используется чуть в другом. А между ними встречается всякая логика RAII, которая позволяет не утечь памяти, но при этом которая сохраняет указатель где-то в своих внутренностях (т.е. создавая возможность для alising'а где-то в другом месте). Или память может выделяться из memory-pool и возвращаться в него неоднократно. Или к ней может быть слишком сложный способ доступа (как, например, в in-place алгоритмах умножения Штрассена, где доказательство отсутствия aliasing — это предмет целой научной статьи).
То есть обычно у компилятора просто недостаточно ресурсов чтобы сохранить это свойство от момента выделения памяти, до момента её использования. Есть десяток мест, где можно эту информацию потерять, так как компилятор не сможет доказать отсутствие aliasing.

Считаю, что наивно было бы полагать, что компилятор сумеет всегда дотащить нужные атрибуты от далёкого new или malloc.
Поэтому, если нужна векторизация в критичном по производительности месте, используют другой подход: пишут restrict у переменных, а не у функций.
В примере по ссылке приведена сигнатура функции
void multiply(float * a, float * b, float * c)

Но гораздо надёжнее было бы просто написать
void multiply(float * a, float * b, float * restrict c)

То есть просто сказать, что программой и программистом гарантируется, что память под c не пересекается с a или b. И пусть компилятор оптимизирует исходя из этой гарантии. А уж каким способом выделена память под матрицы не важно: malloc это, или глобальный массив, или может вообще отображение файла в память.


То есть стоит поступать как обычно: если нужна производительность, то не ограничивать себя возможностями чистого языка, а использовать расширения самому.
Отредактировано 26.04.2018 10:11 watchmaker . Предыдущая версия .
Re[2]: new vs. malloc
От: jazzer Россия Skype: enerjazzer
Дата: 27.04.18 04:28
Оценка:
Здравствуйте, watchmaker, Вы писали:

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


_NN>>Если вручную определить в своём проекте new, то можем получить существенное ускорение

W>Я согласен, что лучше бы иметь такое свойство изначально, чем не иметь. Но не считаю, что этого достаточно.
W>В этом примере память используется сразу после выделения malloc'ом или new. Но как часто такая ситуация встречается в программах?

std::vector<int> v1(100,1), v2(100,2), v3(100,3);
v3[0] = v1[0] + v2[0];

или std::string. или std::unique_ptr. Очень много кода, где создали и тут же работаем, или позвали фабрику, которая, если не злоупотреблять виртуальностью, тоже инлайнится (make_unique, например), поэтому после инлайна будет то же самое, что прямо в коде написал. И кода тут во всех этих объектах реально немного, компилятор вполне способен протащить информацию об алиасинге, если она есть. Но так как тут везде внутри по умолчанию используется new, то будет проблема, описанная _NN_.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.