Russian Qt Forum
Ноябрь 22, 2024, 05:13 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: STL-compatible контейнеры с семантикой Qt's Implicit Sharing  (Прочитано 8215 раз)
AkonResumed
Чайник
*
Offline Offline

Сообщений: 81


Просмотр профиля
« : Октябрь 23, 2020, 14:07 »

Ревизирую старый код, и стоит вопрос рефакторинга QVector->std::vector (также рассматривается std::array для некоторых случаев). Мотивация - иметь выровненные данные в контейнере для последующей оптимизации (векторизации, и в этой связи также рассматривается замена double -> float).

Основная семантическая проблема - использование в QVector Implicit Sharing (copy-on-write) при передаче данных, в основном, между потоками.

Собственно, вопрос - нужен stl::vector c Implicit Sharing семантикой, в идеале - совместимой с Qt, т.е.:
Цитировать
stl::vector v;
QVector qv;
v = qv;  // inc ref. count, not a deep copy

Порекомендуйте хорошие порты STL или просто отдельные библиотеки STL-контейнеров, наделенные данным свойством.

Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #1 : Октябрь 23, 2020, 23:23 »

Цитировать
Порекомендуйте хорошие порты STL или просто отдельные библиотеки STL-контейнеров, наделенные данным свойством.
Боюсь, таких непосредственно в stl нет(
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #2 : Октябрь 24, 2020, 11:17 »

Не понял, зачем такой переход. В QVector, вроде, и так всё выровнено
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Октябрь 24, 2020, 11:24 »

Не понял, зачем такой переход. В QVector, вроде, и так всё выровнено
Да, могу ошибаться, но "боковым зрением" вроде видел в мсходниках что он равняется на 16
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #4 : Октябрь 24, 2020, 12:37 »

QVector выравнивает так как выравнивается T:

Код:
    Q_REQUIRED_RESULT static QTypedArrayData *allocate(size_t capacity,
            AllocationOptions options = Default)
    {
        Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData));
        return static_cast<QTypedArrayData *>(QArrayData::allocate(sizeof(T),
                    Q_ALIGNOF(AlignmentDummy), capacity, options));
    }
Код:
class AlignmentDummy { QArrayData header; T data; };
Записан
AkonResumed
Чайник
*
Offline Offline

Сообщений: 81


Просмотр профиля
« Ответ #5 : Октябрь 24, 2020, 16:20 »

Разумеется, иначе что это за контейнер, которой кладет на заданное выравнивание типа. Он волен нижнюю границу поднять (например, минимум 16 байт) из-за каких-то своих соображений, но опустить - никак. Также и нижележащие malloc/realloc не опускаются ниже определенной величины.

Собственно, если нужно иметь выровненный буфер как таковой, хранящийся в векторе, то достаточно как-то так:
Код:
	
class alignas(256) CacheLine
{
public:
CacheLine(char data = 0) : data_(data) {}
operator char() { return data_; }

private:
char data_;
};

QVector<CacheLine> v;
v.push_back({});
qDebug() << (void*)&v.front();  // выровнен на 256 байт
Но работать с ним поэлементно через интерфейс QVector нельзя: v[1] вернет 257 байт, а не второй.

Для поэлементной работы с байтами можно грубо пропатчить индексный доступ, но тут уже семантические нарушения по типу:
Код:
template <typename T> class MyVector : protected QVector<T> 
{
public:
T& operator[](int index) { return reinterpret_cast<char*>(QVector<T>::data())[index]; }
        ... и так далее для всего, ... итераторов
};
Это все костыли. Нужно просто, чтобы у QVector был аллокатор. Кстати, как думаете - почему его нет? Полагаю, что Qt-контейнеры создавались прежде всего для собственных нужд (типа хранить чилдренов, небольшой мапчик/хэшик и т.п.), где аллокаторы не нужны.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Октябрь 24, 2020, 20:00 »

Нужно просто, чтобы у QVector был аллокатор. Кстати, как думаете - почему его нет? Полагаю, что Qt-контейнеры создавались прежде всего для собственных нужд (типа хранить чилдренов, небольшой мапчик/хэшик и т.п.), где аллокаторы не нужны.
Думаю потому что он (или его наличие) изрядно гадит в консоли, а нужда в нем возникает... "не припомина"

Я немного "потерял нить", верно ли я понимаю что нужен ф-ционал QVector<char> но с выравниванием на заданную кратность (напр 256)? Я бы объявлял вектор структур с нужным выравниванием, а для работы с char'ами, не мудрствуя лукаво, "приводился" бы (в С стиле). Можно использовать стандартное средство range (не помню как называется, множество реализаций было еще до того как оно вошло в стандарт).
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #7 : Октябрь 24, 2020, 20:14 »

Я бы смотрел в сторону сторонних библиотек.. Ну на худой конец, свой велик бы написал.. Кстати, тут товарищ,
navrocky предложил свою реализацию implicit sharing.. http://www.prog.org.ru/topic_15029_0.html
Я бы там её немного бы допилил, в плане конструктора от произвольного числа аргументов..
Но как вариант, можно свою реализацию vector сделать, аналогично Qt.. 
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
AkonResumed
Чайник
*
Offline Offline

Сообщений: 81


Просмотр профиля
« Ответ #8 : Октябрь 25, 2020, 12:35 »

Да, нужен  QVector<char>, такой что первый байт всегда лежит по адресу, кратному 256 (или любому другому, задаваемому статически). Структура байт в векторе - это уже будет двумерный индекс.
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #9 : Октябрь 25, 2020, 13:03 »

Да, нужен  QVector<char>, такой что первый байт всегда лежит по адресу, кратному 256 (или любому другому, задаваемому статически). Структура байт в векторе - это уже будет двумерный индекс.
Ну это не проблема сейчас? Улыбающийся
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Октябрь 25, 2020, 15:13 »

Да, нужен  QVector<char>, такой что первый байт всегда лежит по адресу, кратному 256 (или любому другому, задаваемому статически). Структура байт в векторе - это уже будет двумерный индекс.
Глянул в отладчике, да, "близок локоть да не укусишь". Выравнивание есть, но не видно как подлезть.

Ну а если "не по теме" Улыбающийся? Верную ли цель Вы ставите (выровненный QVector<char>) и стоит ли ее добиваться? С точки зрения "минимум переделок" - скорее всего да. Но если все делать чисто/кошерно (к чему Вы так явно стремитесь) - то скорее нет. Ведь операции с QVector<char>, хотя бы push_back, erase и.т.п. никак не поддерживают целостность выравниваемых структур.
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #11 : Октябрь 25, 2020, 15:16 »

почему нельзя выделить чуть больше и использовать для доступа выровненный span<char>?
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #12 : Октябрь 25, 2020, 15:27 »

почему нельзя выделить чуть больше и использовать для доступа выровненный span<char>?

Не понял, а как он с QVector такой финт может произвести? Или я не догоняю?)
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #13 : Октябрь 25, 2020, 16:13 »

Ну типа не использовать не выровненное начало вектора, а начинать с нужным (выровненным) оффсетом. А span "мимикрирует" под вектор что позволяет АПИ сохранить более менее. Понятно, что все мутабельные операции типа append() мимо.
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #14 : Октябрь 25, 2020, 16:26 »

Ну типа не использовать не выровненное начало вектора, а начинать с нужным (выровненным) оффсетом. А span "мимикрирует" под вектор что позволяет АПИ сохранить более менее. Понятно, что все мутабельные операции типа append() мимо.

Спасибо, более-менее дошло)
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.052 секунд. Запросов: 23.