Уловки, позволяющие избежать псевдонимов указателей в общем кодеC++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 Уловки, позволяющие избежать псевдонимов указателей в общем коде

Сообщение Anonymous »

Это продолжение вопроса «Ограниченный доступ к выделенным массивам, принадлежащим отдельному объекту», после обнаружения того, что возврат по значению между единицами компиляции не помогает намекнуть компилятору о непересекающихся выделениях памяти.
/>У меня есть две функции make_v1 и make_v2, которые возвращают объект, подобный массиву, по значению.
(Это может быть, например, std::vector, важным моментом является то, что конструктор копирования четко распределяет память).

Код: Выделить всё

#include

template void modify_v(It);

void dreaded_function();

template
void foo(It1 a, It2 b) {
*a = 5;
*b = 6;
if(*a == *b) dreaded_function();  // this is never called if a and b do not overlap
}

int main() {
std::vector v1 = make_v1();
std::vector v2 = make_v2();

foo(v1.begin(), v2.begin());
}
Как вы можете видеть в скомпилированном коде, не делается никаких предположений для оптимизации вызова dreaded_function.
Это всего лишь пример псевдонимов указателя, просто для того, чтобы диагностируйте ситуацию.
Имеются хорошо известные случаи псевдонимов указателей, создающих худшие проблемы с производительностью.
https://godbolt.org/z/345PKrsnx
Какие высокоуровневые подсказки я могу дать компилятору в C++ (или, возможно, с использованием расширений), что диапазоны итераторов находятся в областях памяти, которые не могут перекрываться?
Если бы это был C или если бы я использовал указатели и расширения C++, я мог бы использовать __restrict и интерфейс указателя, но мне нужно что-то более высокоуровневое.
(Спасибо @TedLygmo за указание на то, что __restrict каким-то образом работает для итераторов std::vector).
Единственный вариант, который я нашел, — это очень явно указать копия:

Код: Выделить всё

    ...
std::vector v1 = static_cast(make_v1());
std::vector v2 = static_cast(make_v2());
Это, по крайней мере, убеждает clang в том, что оптимизацию можно провести. (и я почти уверен, что ценой дополнительной копии.)
https://godbolt.org/z/nYfKeTKqj
Но это уродливо, и он также создает копию, а также, если make_v станет включенной функцией позже, решение будет иметь свои затраты.
(Кроме того, это все еще не убедит GCC!)Это единственный способ, которым я могу, чтобы компилятор, чем v1 и v2, не перекрывали память? Есть ли более упрощенное решение?
Должно ли [[предполагать]] работать для этого в конечном итоге?

На данный момент лучшее, на что я надеюсь, - это какое-нибудь ключевое слово/ расширение, которое «имитирует» результат make_v1/ копируется в v1/.

Подробнее здесь: https://stackoverflow.com/questions/791 ... neric-code
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»