powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / изменить адрес ссылки
25 сообщений из 63, страница 2 из 3
изменить адрес ссылки
    #38390519
andreybs
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
BagaBagaНо я всё равно не понимаю вашей задачи (да она и не озвучена).

Все просто - создается массив структур:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
struct A 
{
double var_n_const; // значение определяется 1 раз
...
var<double> var_n; // значение меняется при каждом вычислении, значение хранится во внешнем массиве
};

struct В
{
double var_n_const; // значение определяется 1 раз
...
double var_n; // значение меняется при каждом вычислении, значение хранится локально
};



Чтобы обнулить var_n для структур B, нужно в цикле их все перебрать и задать B.var_n=0. В то время для обнуления структур А достаточно с помощью memset обнулить массив, где хранятся значения. Если обнуление делается много миллионов раз, то второй способ быстрее. Аналогично, можно в любой момент сделать "снимок" системы, сохранив массив значений в отдельный буфер и восстановить систему, загрузив массив из буфера. Опять же это быстрее циклического перебора структур.

BagaBagaсоздание простого массива (через new) и его последующая инициализация с memset по сравнению с vector<int>v(elem_number, 0) давало выигрыш менее 0.5%.

А кто сказал, что внешним массивом не может быть вектор? Речь идет не об инициализации массива, а о массовых операциях изменения значений массива в сравнении с изменением значений каждой структуры в цикле.
...
Рейтинг: 0 / 0
изменить адрес ссылки
    #38390537
Anatoly MoskovskyandreybsИзвестно, что обращение к переменной по указателю type* осуществляется в два шага: считывание адреса из указателя, переход по адресу. В то же время ссылка type& содержит прямой адрес на значение переменной в памяти, поэтому обращение по ссылке занимает на один шаг меньше. При выполнении высокопроизводительных операций эта разница ощутима
Это не так.
На уровне машинного кода реализация указателя и ссылки одинаковая, поэтому никакой разницы в скорости у них нет. (Где вы вообще про такое прочли?)

Соответственно, необходимость изменения ссылок надумана. Используйте указатели.
Ссылка int & соответствует int *const __restrict - в этом случае они всегда соптимизируются одинаково. Если указатель без const или __restrict, то у него меньше возможностей к оптимизации, чем у ссылки.
...
Рейтинг: 0 / 0
изменить адрес ссылки
    #38390539
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
int *const __restrict,

А сможете привести пример, когда будет разный код сгенерирован? :)
...
Рейтинг: 0 / 0
изменить адрес ссылки
    #38390541
andreybs
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
int *const __restrict,

Если обычному указателю приписать __restrict, то у него будет больше возможностей к оптимизации?

т.е. в моем случае вместо
T* _ptr;
использовать
T* __restrict _ptr;

Есть еще хинты в оптимизации работы указателей, на которые следует обратить внимание?
...
Рейтинг: 0 / 0
изменить адрес ссылки
    #38390543
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andreybs,

Вы не до конца поняли. Нужно и const и __restrict.
То есть вы не сможете в указатель присваивать :)
...
Рейтинг: 0 / 0
изменить адрес ссылки
    #38390547
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Топикстартеру на заметку:
Вообще, обнуление структур через memset - штука небезопасная, надо знать, какие структуры. POD структуры — все будет ок. Не POD — будет беда.
...
Рейтинг: 0 / 0
изменить адрес ссылки
    #38390552
BagaBaga
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andreybs,
похоже, я не могу понять вас (используемую вами терминологию).

Если у нас есть массив
my_class arr[100]
то у меня в каждом элементе массива хранится одна структура.
Это значит, что я её могу обойти, например, так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
struct A{
    int a;
};

int main()
{
    A a[100];
    int i =0;
    for(auto& e : a){
        e.a=i++;
    }
    a[12].a=-1;
    for(const auto& e : a)
    {
        cout << e.a << endl;
    }  
   return 0;
}



Я это к тому, что в любом случае ваше var<double> var_n хранится в структуре. Это, конечно, может быть указатель (или ссылка) на что-то "снаружи". И вот тут я начинаю непонимать: речь идёт об "очистке" одной структуры? Тогда вы работаете с одной единицей и "валовые операции" вам не нужны. Вы меняете что-то для "кучи" структур? Но как тогда построить соответствие между местом в массиве (или векторе или что вы там используете) и местом в этом "снаружи"?

То, что вы озвучиваете, мне напоминает ситуацию:
у меня есть два поля, одно из которых меняется редко, а другое - часто. Заведу под них массивы:
double rare[maxsize]
double freq[maxsize]
Но мне же почему-то неудобно показать, что это два массива. Поэтому я сделаю псевдообвязку, в которой одно поле будет указывать (а уж как - через указатели или ссылки - не важно) на rare[i], а во второй - на freq[i]. И заведу массив такого же размера для обвязок (не создавать же ручками кучу переменных). Вот только тогда и можно "показать фокус" и почистить скопом freq, не пробегаясь по массиву обвязок. Но это автоматически означает, что у вас в массиве freq могут храниться только "плоские" POD-типы. Про структуры и классы придётся забыть - по причине особенностей хранения данных (например, вследствие выравнивания структур) как минимум.

А так, без примера очищения "скопом", я не могу понять, о чём вообще речь.
...
Рейтинг: 0 / 0
изменить адрес ссылки
    #38390620
andreybs
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZivТопикстартеру на заметку:
Вообще, обнуление структур через memset - штука небезопасная, надо знать, какие структуры. POD структуры — все будет ок. Не POD — будет беда.

Обнуляются не структуры, а только некоторые их члены, значение которых вынесено в отдельный массив данных по указателю. В итоге обнуляется массив данных, а не массив структур.
...
Рейтинг: 0 / 0
изменить адрес ссылки
    #38390624
andreybs
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
BagaBagaТо, что вы озвучиваете, мне напоминает ситуацию:
у меня есть два поля, одно из которых меняется редко, а другое - часто. Заведу под них массивы:
double rare[maxsize]
double freq[maxsize]
Но мне же почему-то неудобно показать, что это два массива. Поэтому я сделаю псевдообвязку, в которой одно поле будет указывать (а уж как - через указатели или ссылки - не важно) на rare[i], а во второй - на freq[i]. И заведу массив такого же размера для обвязок (не создавать же ручками кучу переменных). Вот только тогда и можно "показать фокус" и почистить скопом freq, не пробегаясь по массиву обвязок.

Вы все верно поняли. Такой "изворот" нужен из-за того, что сами вычисления делаются поэлементо со структурами и их членами (от этого не уйти), а инициализация данных для вычислений осуществляется массово за один раз через внешние массивы с данными (для ускорения каждого цикла вычислений).
...
Рейтинг: 0 / 0
изменить адрес ссылки
    #38390628
andreybs
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly Moskovskyandreybs,

Вы не до конца поняли. Нужно и const и __restrict.
То есть вы не сможете в указатель присваивать :)

Если я правильно понял, что написано здесь и здесь , то __restrict имеет определенный смысл - мы как бы привязываем указатель к определенной области памяти и обещаем его не перезаписывать указателями из других областей. Как раз мой случай, а отсутствие const как раз разрешает менять указатель. Полагаю, нельзя будет ему присваивать NULL - не проблема, можно инициализировать статической переменной типа static T __restrict init_var; (если такая запись проканает). Вобщем, надо будет попробовать и посмотреть на изменение скорости работы...
...
Рейтинг: 0 / 0
изменить адрес ссылки
    #38391028
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andreybs,

Да не будет никакого изменения в скорости.
Вы не там оптимизируете.
Оптимизировать надо алгоритм, а не машинный код.
...
Рейтинг: 0 / 0
изменить адрес ссылки
    #38391113
*const __restrict
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly Moskovskyint *const __restrict,

А сможете привести пример, когда будет разный код сгенерирован? :)
Сходу не приведу, но недавно встречался как раз такой случай, когда заданные в коде константы в compile-time проваливались глубоко внутрь кода через *const __restrict, и сильно оптимизировали код, в том время, как без этих квалификаторов такого не происходило.

andreybs ,
Вообще это C-style подход.
А в C++ нет ничего проще, чем использовать ссылку &, если мы конечно работаем не в google, где разрешены только константные ссылки в параметрах функций :)
...
Рейтинг: 0 / 0
изменить адрес ссылки
    #38391439
BagaBaga
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andreybsОбнуляются не структуры, а только некоторые их члены, значение которых вынесено в отдельный массив данных по указателю. В итоге обнуляется массив данных, а не массив структур.
Вот тут у меня с вами принципиальное расходение в терминологии: ничего в структурах не обнуляется. Там как хранились "редкие данные", так и хранятся. Как хранился адрес (в виде указателя или ссылки - не важно) на "частые" данные, так и хранится. А что происходит с тем куском памяти, ссылка на который хранится в структуре, структуре глубоко всё равно - хоть обнуляйте, хоть генератором случайных чисел заполняйте.

И да, похоже, сначала нужно хорошо оптимизировать алгоритм, а уже потом пытаться выиграть на "массовом заполнении" вместо "индивидуального".
...
Рейтинг: 0 / 0
изменить адрес ссылки
    #38391501
andreybs
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
*const __restrict andreybs ,
Вообще это C-style подход.
А в C++ нет ничего проще, чем использовать ссылку &, если мы конечно работаем не в google, где разрешены только константные ссылки в параметрах функций :)

Мне нужно инициализировать ссылку не в момент создания экземпляра содержащий ее структуры, а после создания всех экземпляров структур.

Кстати, я стараюсь везде использовать константные ссылки в качестве параметров функций... :) Не знаю, как там оптимизатор решит, но так точно не будет создаваться копии параметра в области видимости функции...
...
Рейтинг: 0 / 0
изменить адрес ссылки
    #38391503
andreybs
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
BagaBagaВот тут у меня с вами принципиальное расходение в терминологии: ничего в структурах не обнуляется. Там как хранились "редкие данные", так и хранятся. Как хранился адрес (в виде указателя или ссылки - не важно) на "частые" данные, так и хранится. А что происходит с тем куском памяти, ссылка на который хранится в структуре, структуре глубоко всё равно - хоть обнуляйте, хоть генератором случайных чисел заполняйте.


Разумеется, в структурах физически ничего не обнуляется, ведь они содержат указатели. :)

BagaBagaИ да, похоже, сначала нужно хорошо оптимизировать алгоритм, а уже потом пытаться выиграть на "массовом заполнении" вместо "индивидуального".

Какая основная идея оптимизации многократно повторяющейся последовательности? - Упростить тело цикла.
Вот как раз замена вложенных циклов на "массовые операции" и позволяют ускорить тело цикла, пусть даже в ущерб быстродействию подготовки данных.
...
Рейтинг: 0 / 0
изменить адрес ссылки
    #38392842
BagaBaga
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если нельзя, но очень хочется, то ...
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
#include <iostream>

using namespace std;

struct S{
    int& a;
    int& b;
    S(int& _a, int& _b):a{_a},b{_b}{};
    S(const S& s):a{s.a},b{s.b}{};
};

int main()
{
    int i =0, j=1, k=2, l=3;
    S s1(i,j); // bind struct references
    S s2(k,l);// another ont
    S s3(s2);//s3 is pointing to k and l
    cout <<&k << endl << &s2.a << endl << &s3.a << endl <<"Hello World" << endl;
    
    // !!!VERY!!! DIRTY TRICK
    //never do it unless you really understand what is going on
    // and have no any - ANY - other way
       ::new (static_cast<void*>(&s3)) S(s1);     
    // now s3 is pointing to i and j - the same as s1

    cout <<&i << endl << &s1.a << endl << &s3.a << endl <<"Hello World" << endl;
    cout << "i was          " << i << endl;
    s3.a = -100;
    cout << "and now i is   " << i << endl;
    i = 111111;
    cout << "and again i is " <<s3.a << endl;
  
   return 0;
}




andreybsКакая основная идея оптимизации многократно повторяющейся последовательности? - Упростить тело цикла.
Вот как раз замена вложенных циклов на "массовые операции" и позволяют ускорить тело цикла, пусть даже в ущерб быстродействию подготовки данных.
Очень просто - путём уменьшения количества операций. Т.е. выноса обнулений за циклы и т.п.

Используемый вами механизм тоже не даётся даром. Вы используете по одной ссылке на каждый элемент массива (в своей структуре-обёртке). Она не даётся даром. На указатель нужна память, в размере (в большинстве реализаций) 32bit (64-разрядные системы для простоты не рассматриваю). Это значит, что для "частых" данных вы практически удваиваете необходимое количество памяти - на сами данные и на указатель на эти данные.
...
Рейтинг: 0 / 0
изменить адрес ссылки
    #38392889
andreybs
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
BagaBagaЕсли нельзя, но очень хочется, то ...


Я думал об этом. Отказался от этого подхода из-за того, что в структурах есть еще и массивы указателей на другие связанные структуры. Частое копирование массивов - дело невыгодное для производительности, а передача ссылки на массив по цепочке выглядит не слишком красиво и не прозрачно. Непонятно, кто должен уничтожать массив при уничтожении структуры, значит потребуется добавить деструктор и т.д. структура плавно превращается в класс...

BagaBagaИспользуемый вами механизм тоже не даётся даром. Вы используете по одной ссылке на каждый элемент массива (в своей структуре-обёртке). Она не даётся даром. На указатель нужна память, в размере (в большинстве реализаций) 32bit (64-разрядные системы для простоты не рассматриваю). Это значит, что для "частых" данных вы практически удваиваете необходимое количество памяти - на сами данные и на указатель на эти данные.

Согласен, ничего не дается даром, я жертвую избыточным объемом данных. Но в моем случае это приемлемые потери, ибо одновременно удерживаемых в памяти структур с такими указателями не так много (не более 2-3 тыс), а вот обращение к ним весьма интенсивное. Да и "частых" данных всего 3 поля double, но они ооочень "частые"... :)
...
Рейтинг: 0 / 0
изменить адрес ссылки
    #38392891
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andreybs,

А что за прикладная область?
...
Рейтинг: 0 / 0
изменить адрес ссылки
    #38392914
BagaBaga
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andreybs,
вообще-то этот код
Код: plaintext
1.
::new (static_cast<void*>(&s3)) S(s1);


делает ровно то, что спрашивается в заголовке топика: он изменяет адрес ссылки (в данном случае две ссылки, хранящиеся внутри структуры). Или вам было нужно что-то другое? Но тогда что?
...
Рейтинг: 0 / 0
изменить адрес ссылки
    #38392918
BagaBaga
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если нужно пересвязать с другими переменными, то можно и так (используя другой конструктор)
Код: plaintext
1.
::new (static_cast<void*>(&s3)) S(v1,v2); 


в s3 будут храниться ссылки на v1 и v2, вне зависимости от того, но что они ссылались раньше.
...
Рейтинг: 0 / 0
изменить адрес ссылки
    #38392975
andreybs
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly Moskovskyandreybs,

А что за прикладная область?

Нейронные сети. Иду на рекорд... :)
...
Рейтинг: 0 / 0
изменить адрес ссылки
    #38392977
andreybs
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
BagaBagaandreybs,
вообще-то этот код
Код: plaintext
1.
::new (static_cast<void*>(&s3)) S(s1);


делает ровно то, что спрашивается в заголовке топика: он изменяет адрес ссылки (в данном случае две ссылки, хранящиеся внутри структуры). Или вам было нужно что-то другое? Но тогда что?

Вы все верно ответили по теме, спасибо за совет. Просто момент создания темы я ошибочно полагал, что ссылки по определению быстрее указателей... Спасибо форумчанам, помогли разобраться и это помогло мне найти неплохое решение.
...
Рейтинг: 0 / 0
изменить адрес ссылки
    #38392996
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andreybsAnatoly Moskovskyandreybs,

А что за прикладная область?

Нейронные сети. Иду на рекорд... :)
А, тупиковая ветвь ИИ.
Самое неблагодарное занятие - оптимизировать по крохам алгоритм, чью работоспособность еще предстоит доказать :)
...
Рейтинг: 0 / 0
изменить адрес ссылки
    #38393120
andreybs
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly MoskovskyА, тупиковая ветвь ИИ.
Самое неблагодарное занятие - оптимизировать по крохам алгоритм, чью работоспособность еще предстоит доказать :)

Довольно субъективное и весьма спорное утверждение. :)
...
Рейтинг: 0 / 0
изменить адрес ссылки
    #38393177
?
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
?
Гость
andreybs, у вас обнуление - это самая частая операция с данными, чтобы оптимизировать скорость ее выполнения за счет замедления других операций?
...
Рейтинг: 0 / 0
25 сообщений из 63, страница 2 из 3
Форумы / C++ [игнор отключен] [закрыт для гостей] / изменить адрес ссылки
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]