Про выравнивание данных - страница 3

[Удален]  
Всем кто отписывается о результатах - спасибо.
[Удален]  

Я тут до этого ещё одно сообщение оставлял, но его удалили. Там была интересная ссылка https://habr.com/en/post/423575/. Вот такой он маркетинг прогресс.

Проектные нормы в микроэлектронике: где на самом деле 7 нанометров в технологии 7 нм?
Проектные нормы в микроэлектронике: где на самом деле 7 нанометров в технологии 7 нм?
  • habr.com
Современные микроэлектронные технологии — как «Десять негритят». Стоимость разработки и оборудования так велика, что с каждым новым шагом вперёд кто-то отваливается. После новости об отказе GlobalFoundries от разработки 7 нм их осталось трое: TSMC, Intel и Samsung. А что такое, собственно “проектные нормы” и где там тот самый заветный размер 7...
 
Vict:

Если вы не можете грамотно организовать хранения данных, то может кодить это не ваше? Разбейте большой массив на массивы с одинаковыми требованиями по выравниванию. Придумываете проблему на ровном месте. 

Я то умею грамотно организовывать хранение данных, ибо не использую выравнивание.  А свои костыли сами используйте.  Проблему как-раз придумали вы в этой ветке, и перекидываете с больной головы на здоровую.  У всех всё прекрасно работает.

Речь то о другом - используют любителей прогресса в хвост и гриву. 

Ну-ну... Пока мы видим, что в хвост и гриву имеют только вас, с вашим архаичным процом )

[Удален]  
Alexey Navoykov:

Злой какой-то, наверное велосипеда нет.

 
Можно заметить, что не просматривается особой связи между приростом производительности и выравниванием. У меня же всё иначе (неверное выравнивание даёт замедление в 1.5-2 раза)
Автор топика (цитата из первого сообщения) удален, к сожалению. Реанимирую тему из-за такой зависимости производительности.

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Библиотеки: Virtual

fxsaber, 2024.11.13 16:57

Заметил зависимость производительности библиотеки от длины статического массива.

Объяснить такую разницу (> 10%) не получается, кроме как странностями связки компилятора и конфигурации машины.


Кратко, увеличили массив и получили бесплатное ускорение.


Набросал исследовательский код.

#define AMOUNT 300 // Числов элементов статического массива.
#define SIZE   279 // Начальный sizeof элементов статического массива.

// Копирование постоянного числа элементов.
template <typename T>
int Func( const T &Array[] )
{
  int Sum = 0;
  T a;
  
  for (int k = 0; k < 1e4; k++)
    for (int j = 0; j < 5e4 / AMOUNT; j++)
      for (uint i = 0; i < AMOUNT; i++)
      {
        a = Array[i]; // Копирование.
        
        Sum += a.i;
      }
    
  return((bool)(Sum + 1) ? sizeof(T) : 0);
}

#define BENCH(A)                                                                             \
  {                                                                                          \
    const ulong StartTime = GetMicrosecondCount();                                           \
    Print((string)(A) + " bytes: " + (string)(GetMicrosecondCount() - StartTime) + " mcs."); \
  } 

// Создает массив структур заданной длины и измеряет время копирования постоянного числа его элементов.
#define BENCH2(A)        \
{                        \
  struct STRUCT##A       \
  {                      \
    int i;               \
    uchar Tmp[SIZE + A]; \
  } Array##A[AMOUNT];    \
                         \
  BENCH(Func(Array##A)); \
}
  
void OnStart()
{
  Print("Compiler Version: " + (string)__MQLBUILD__ + " " + __CPU_ARCHITECTURE__ +
        ", AMOUNT = " + (string)(AMOUNT));  
  
  // https://www.mql5.com/ru/forum/474452/page21#comment_55112615
  // Измеряем время копирования для массивов разного sizeof-элементов.
  BENCH2(0)
  BENCH2(1)
  BENCH2(2)
  BENCH2(3)
  BENCH2(4)
  BENCH2(5)
  BENCH2(6)
  BENCH2(7)
  BENCH2(8)
  BENCH2(9)
  BENCH2(10)
  BENCH2(11)
  BENCH2(12)
  BENCH2(13)
  BENCH2(14)
  BENCH2(15)
  BENCH2(16)
  BENCH2(17)
  BENCH2(18)
  BENCH2(19)
}

В общем, беру статические массивы с разным sizeof его элементов. И замеряю время работы с ними.


Ниже промежуточные результаты.


Длина статического массива.

AMOUNT = 70.

Compiler Version: 4678 AVX, AMOUNT = 70
283 bytes: 10 mcs.
284 bytes: 0 mcs.
285 bytes: 0 mcs.
286 bytes: 1 mcs.
287 bytes: 0 mcs.
288 bytes: 1 mcs.
289 bytes: 0 mcs.
290 bytes: 1 mcs.
291 bytes: 0 mcs.
292 bytes: 0 mcs.
293 bytes: 0 mcs.
294 bytes: 0 mcs.
295 bytes: 1 mcs.
296 bytes: 0 mcs.
297 bytes: 0 mcs.


AMOUNT = 80.

Compiler Version: 4678 AVX, AMOUNT = 80
283 bytes: 137139 mcs.
284 bytes: 135945 mcs.
285 bytes: 135483 mcs.
286 bytes: 137699 mcs.
287 bytes: 138214 mcs.
288 bytes: 136563 mcs.
289 bytes: 139492 mcs.
290 bytes: 139307 mcs.
291 bytes: 139245 mcs.
292 bytes: 140320 mcs.
293 bytes: 139092 mcs.
294 bytes: 138240 mcs.
295 bytes: 137167 mcs.
296 bytes: 137203 mcs.
297 bytes: 136400 mcs.
298 bytes: 136422 mcs.
299 bytes: 136075 mcs.
300 bytes: 138047 mcs.
301 bytes: 136091 mcs.
302 bytes: 136983 mcs.


Почему длина массива 70 дает мгновенное выполнение - загадка. Выглядит, как баг.


sizeof-элемента массива.

AMOUNT = 200.

Compiler Version: 4678 AVX, AMOUNT = 200
283 bytes: 97397 mcs.
284 bytes: 76152 mcs.
285 bytes: 81791 mcs.
286 bytes: 79203 mcs.
287 bytes: 81618 mcs.
288 bytes: 77106 mcs.
289 bytes: 79736 mcs.
290 bytes: 76282 mcs.
291 bytes: 82818 mcs.
292 bytes: 75829 mcs.
293 bytes: 171046 mcs.
294 bytes: 75766 mcs.
295 bytes: 80362 mcs.
296 bytes: 75445 mcs.
297 bytes: 79826 mcs.
298 bytes: 94526 mcs.
299 bytes: 84957 mcs.
300 bytes: 76663 mcs.
301 bytes: 80008 mcs.
302 bytes: 75509 mcs.


AMOUNT = 300.

Compiler Version: 4678 AVX, AMOUNT = 300
283 bytes: 94590 mcs.
284 bytes: 77835 mcs.
285 bytes: 99202 mcs.
286 bytes: 120298 mcs.
287 bytes: 99922 mcs.
288 bytes: 77485 mcs.
289 bytes: 85059 mcs.
290 bytes: 76298 mcs.
291 bytes: 83804 mcs.
292 bytes: 81790 mcs.
293 bytes: 212770 mcs.
294 bytes: 75129 mcs.
295 bytes: 74594 mcs.
296 bytes: 74414 mcs.
297 bytes: 85595 mcs.
298 bytes: 106357 mcs.
299 bytes: 120836 mcs.
300 bytes: 86000 mcs.
301 bytes: 97952 mcs.
302 bytes: 97765 mcs.


Воспроизводимое замедление в 2-3 раза для массивов с sizeof = 293.


Однозначно, что для скорости имеет смысл добавлять структуры до оптимальных по производительности размеров. Потому что можно запросто просесть в производительности, если нарваться на неудачный размер, как в примере выше.

 
Compiler Version: 4678 AVX2 + FMA3, AMOUNT = 300
283 bytes: 105689 mcs.
284 bytes: 106489 mcs.
285 bytes: 104347 mcs.
286 bytes: 104872 mcs.
287 bytes: 104167 mcs.
288 bytes: 106751 mcs.
289 bytes: 107583 mcs.
290 bytes: 104718 mcs.
291 bytes: 102016 mcs.
292 bytes: 103100 mcs.
293 bytes: 125250 mcs.
294 bytes: 104654 mcs.
295 bytes: 104261 mcs.
296 bytes: 102658 mcs.
297 bytes: 103508 mcs.
298 bytes: 107471 mcs.
299 bytes: 105609 mcs.
300 bytes: 106154 mcs.
301 bytes: 104678 mcs.
302 bytes: 102446 mcs.
Compiler Version: 4678 AVX, AMOUNT = 300
283 bytes: 89110 mcs.
284 bytes: 89111 mcs.
285 bytes: 89706 mcs.
286 bytes: 95375 mcs.
287 bytes: 90327 mcs.
288 bytes: 92335 mcs.
289 bytes: 89914 mcs.
290 bytes: 89631 mcs.
291 bytes: 89621 mcs.
292 bytes: 89137 mcs.
293 bytes: 132522 mcs.
294 bytes: 89528 mcs.
295 bytes: 88261 mcs.
296 bytes: 89201 mcs.
297 bytes: 91234 mcs.
298 bytes: 91184 mcs.
299 bytes: 90914 mcs.
300 bytes: 88948 mcs.
301 bytes: 88537 mcs.
302 bytes: 87502 mcs.
 
Alain Verleyen #:

AVX2 работает медленнее, чем AVX. При этом у первого слабее просидание производительности для sizeof=293, чем у второго.

 
fxsaber #:

Длина статического массива.

Compiler Version: 4678 AVX, AMOUNT = 100
274 bytes: 141050 mcs.
275 bytes: 140785 mcs.
276 bytes: 139779 mcs.
277 bytes: 138698 mcs.
278 bytes: 139524 mcs.
279 bytes: 140143 mcs.
280 bytes: 140138 mcs.
281 bytes: 139383 mcs.
282 bytes: 140267 mcs.
283 bytes: 138571 mcs.
Compiler Version: 4678 AVX, AMOUNT = 200
274 bytes: 82901 mcs.
275 bytes: 79067 mcs.
276 bytes: 81715 mcs.
277 bytes: 87911 mcs.
278 bytes: 81248 mcs.
279 bytes: 97236 mcs.
280 bytes: 83428 mcs.
281 bytes: 78119 mcs.
282 bytes: 82702 mcs.
283 bytes: 82348 mcs.

Увеличили статический массив в два раза, и он стал копироваться почти в два раза быстрее!

 

У тебя UB. Ты никак не инициализируешь поле i.

Компилятор может доказать, что никогда нет передачи ссылки на массив в функцию, он у тебя всегда создается как xvalue и создается с default конструктором.

На основании этого, при инстанцировании шаблона, он имеет право вообще функцию не создавать, а все заинлайнить, а далее, учитывая UB, все свести к аналогу return sizeof(T)

 
Vladimir Simakov #:

У тебя UB. Ты никак не инициализируешь поле i.

Проверял с инициализацией - аналогично.

#define BENCH2(A)                  \
{                                  \
  struct STRUCT##A                 \
  {                                \
    int i;                         \
    uchar Tmp[SIZE + A];           \
  } Array##A[AMOUNT];              \
                                   \
  for (int i = 0; i < AMOUNT; i++) \
    Array##A[i].i = 1;             \
                                   \
  BENCH(Func(Array##A));           \
}

Компилятор может доказать, что никогда нет передачи ссылки на массив в функцию, он у тебя всегда создается как xvalue и создается с default конструктором.

На основании этого, при инстанцировании шаблона, он имеет право вообще функцию не создавать, а все заинлайнить, а далее, учитывая UB, все свести к аналогу return sizeof(T)

Распечатывал сумму - все правильно.

  Print(Sum);
    
  return((bool)(Sum + 1) ? sizeof(T) : 0);


На скорость выполнения эти оба добавления не влияют. Сумму возвращают одну и ту же. Только для AMOUNT=50 выполнение идет в 500 раз быстрее, чем для AMOUNT = 100.

Compiler Version: 4678 AVX, AMOUNT = 100
500000000
283 bytes: 136350 mcs.
500000000
284 bytes: 105691 mcs.
500000000
285 bytes: 137357 mcs.
500000000
286 bytes: 105529 mcs.
500000000
Compiler Version: 4678 AVX, AMOUNT = 50
500000000
283 bytes: 270 mcs.
500000000
284 bytes: 280 mcs.
500000000
285 bytes: 321 mcs.
500000000