Re[6]: Умный вопрос по C/C++
От: Erop Россия  
Дата: 24.08.07 11:10
Оценка:
AP>А если эти данные в буфере? Буфер будет выровнен, а начало структуры данных может и небыть.
Просто скопируй...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: Умный вопрос по C/C++
От: remark Россия http://www.1024cores.net/
Дата: 24.08.07 11:13
Оценка:
Здравствуйте, Erop, Вы писали:

E>Ну, например, если железо фиксирует endian, то ты, читая int как коллекцию char получаешь уже вполне определённое поведение...


Показательный пример ты можешь видеть в первом посте этого топика


1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[7]: Умный вопрос по C/C++
От: Alexander Pazdnikov  
Дата: 24.08.07 11:28
Оценка:
Здравствуйте, Erop, Вы писали:

AP>>А если эти данные в буфере? Буфер будет выровнен, а начало структуры данных может и небыть.

E>Просто скопируй...

Полностью согласен.
В принципе, про другое говорил — не нужно в телемеханике жертвовать надежностью ради сомнительного выигрыша по скорости.
Вот.
Re[5]: aliasing и aligning
От: McSeem2 США http://www.antigrain.com
Дата: 24.08.07 16:19
Оценка:
Здравствуйте, remark, Вы писали:


R>Не путайте aliasing и aligning!

R>Это обе засады в С++. Но тем не менее — очень разные вещи

Совершенно верно. Путаница возможно была инициирована мной, http://www.rsdn.ru/forum/message/2631085.1.aspx
Автор: McSeem2
Дата: 23.08.07

Вот этой строчкой:
return (int*)(&mem_pool[index_aligned_to_int]);  // To UB or not to UB?


Но эти вещи ортогональны, хотя в данном случае необходимо учитывать и то и другое.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[4]: Умный вопрос по C/C++
От: McSeem2 США http://www.antigrain.com
Дата: 24.08.07 16:23
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Здесь нет запрещения "простого свопинга байт/слов".

Ш>Запрет на подобный аллиазинг -- вещь совершенно правильная, особенно для низкоуровнего программирования, поскольку помогает оптимизации кода.
Ш>Ну и как человек, который имеет некий опыт возни с разным железом -- не встречал я ещё ни разу реальной необходимости применять грязные хаки.
Ш>Обычно это делают от недостака опыта. А иногда всречается просто патологическая глупость помноженная на самоуверенность, когда человек начинает memcpy на C писать, думая, что у него получится лучше чем а CRTL.

Вот ты, как мощный Шахтер и объясни мне, как я могу написать собственный аллокатор, 100% соблюдая правило strict aliasing. Или аллокаторы пишутся тоже из за "патологической глупости помноженной на самоуверенность"?
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[6]: Умный вопрос по C/C++
От: Шахтер Интернет  
Дата: 24.08.07 23:33
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Шахтер, Вы писали:


Ш>>
Ш>>    rol    ecx, 16                    ; 00000010H
Ш>>


E>А это точно быстрее обмена слов?


В большинстве современных процессоров самая дорогая операция -- обмен с памятью. Битовые же операции обычно очень дешевые (что не удивительно -- они тривиально реализуютя схемотехнически).
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[5]: Умный вопрос по C/C++
От: Шахтер Интернет  
Дата: 24.08.07 23:37
Оценка:
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, Шахтер, Вы писали:


E>>>McSeem2 прав -- такая паранойя. Если уж C/C++ позиционируются как языки для работы непосредственно с железом, то запрещение простого свопинга байт/слов выглядит полным маразмом.


Ш>>Здесь нет запрещения "простого свопинга байт/слов".

Ш>>Запрет на подобный аллиазинг -- вещь совершенно правильная, особенно для низкоуровнего программирования, поскольку помогает оптимизации кода.
Ш>>Ну и как человек, который имеет некий опыт возни с разным железом -- не встречал я ещё ни разу реальной необходимости применять грязные хаки.
Ш>>Обычно это делают от недостака опыта. А иногда всречается просто патологическая глупость помноженная на самоуверенность, когда человек начинает memcpy на C писать, думая, что у него получится лучше чем а CRTL.

E>Ну если оставить в стороне излишнюю самоуверенность, то такие вещи, как:

E>* буфера ввода-вывода, указатели на которые передаются либо как void*, либо как char*;
E>* средства отладочных дампов блоков памяти, которые воспринимают void*, а затем преобразовывают его к char*.

E>они так же нелегальны?


Что именно нелегально?
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[7]: Умный вопрос по C/C++
От: Шахтер Интернет  
Дата: 24.08.07 23:47
Оценка: :)
Здравствуйте, Bell, Вы писали:

B>Здравствуйте, Шахтер, Вы писали:


B>Поправь меня, но ИМХО приведенный вариант с объединением в точности соответствует приведенному тобой первому варианту, который "will work as expected".

B>

Смысл: код нелегален, но текущая версия компилятора так делать позволяет даже при включённом strict-aliasing. Потому что надо поддерживать сущестующий код.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[7]: Умный вопрос по C/C++
От: Erop Россия  
Дата: 24.08.07 23:57
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>>>
Ш>>>    rol    ecx, 16                    ; 00000010H
Ш>>>


E>>А это точно быстрее обмена слов?


Ш>В большинстве современных процессоров самая дорогая операция -- обмен с памятью. Битовые же операции обычно очень дешевые (что не удивительно -- они тривиально реализуютя схемотехнически).


С памятью — да. С кэшем -- не факт...
А с другой стороны тут на 16 двигать надо. Если это таки в цикле делается...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Умный вопрос по C/C++
От: Шахтер Интернет  
Дата: 25.08.07 01:12
Оценка: 2 (1)
Здравствуйте, McSeem2, Вы писали:

MS>Здравствуйте, Шахтер, Вы писали:


Ш>>Здесь нет запрещения "простого свопинга байт/слов".

Ш>>Запрет на подобный аллиазинг -- вещь совершенно правильная, особенно для низкоуровнего программирования, поскольку помогает оптимизации кода.
Ш>>Ну и как человек, который имеет некий опыт возни с разным железом -- не встречал я ещё ни разу реальной необходимости применять грязные хаки.
Ш>>Обычно это делают от недостака опыта. А иногда всречается просто патологическая глупость помноженная на самоуверенность, когда человек начинает memcpy на C писать, думая, что у него получится лучше чем а CRTL.

MS>Вот ты, как мощный Шахтер и объясни мне, как я могу написать собственный аллокатор, 100% соблюдая правило strict aliasing.


Я, кажется понял, что тебя смущает. Ты просто не совсем правильно понимаешь, что именно запрещено делать. Не закапываясь в текст стандарта, просто напишу несколько примеров.

Легально.

int a=...;
unsigned *b=(unsigned *)(void *)&a;

printf("%u\n",*b);


Нелегально.

int a=...;
short *b=(short *)(void *)&a;

printf("%u\n",*b);


Опять легально (сюрприз!).

int a;
char *c=(char *)(void *)&a;

c[0]=...;
c[1]=...;
c[2]=...;
c[3]=...;

printf("%d\n",a);


Манипуляции с указателями вообще под эту статью не попадают. Попадает только доступ.

Bottomline is. Если есть два объекта A *a; B *b; физическое местоположение которых пересекаются (как такое может случится -- отдельный больной вопрос), то значения этих объектов рассматриваются как "связанные" только в четко перечисленных случаях. Во всех остальных случах попытка изменить значение одного объекта меняя значение другого нелегальна. Проще говоря, результаты оптимизации будут непредсказуемые. Как в приведённом изначально примере, компилятор просто счел что вызов функции не имеет видимых побочных эффектов и выбросил его.

MS>Или аллокаторы пишутся тоже из за "патологической глупости помноженной на самоуверенность"?


Нет. Это я вообще не про тебя. Где моя большая кружка пива?
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[8]: Умный вопрос по C/C++
От: Шахтер Интернет  
Дата: 25.08.07 02:00
Оценка: 1 (1)
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Шахтер, Вы писали:


Ш>>>>
Ш>>>>    rol    ecx, 16                    ; 00000010H
Ш>>>>


E>>>А это точно быстрее обмена слов?


Ш>>В большинстве современных процессоров самая дорогая операция -- обмен с памятью. Битовые же операции обычно очень дешевые (что не удивительно -- они тривиально реализуютя схемотехнически).


E>С памятью — да. С кэшем -- не факт...


Не забывай, что в первом случае у нас два чтения и две записи, а во втором по одной.

E>А с другой стороны тут на 16 двигать надо. Если это таки в цикле делается...


Barrel-shifter

Хотя раньше -- таки да.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[8]: Умный вопрос по C/C++
От: Шахтер Интернет  
Дата: 25.08.07 03:27
Оценка: 10 (1)
Здравствуйте, Erop, Вы писали:

Короче. Исследовал я вопрос (вообще, в подобных случаях надо не гадать, а мерить). На моём нотеке (T7200 2Ghz) оба метода практически эквивалентны по скорости.

/* main.cpp */ 

#include <stdio.h>

typedef unsigned long long uint64;

/* CPUClock() */ 

__declspec(naked) uint64 CPUClock()
 {
  __asm {
           rdtsc
           ret
        }
 }
 
unsigned SwapHalf(unsigned val)
 {
  return (val<<16)|(val>>16);
 }
 
/* test1()  */  

void test1()
 {
  static volatile unsigned val=0x11112222;
 
  val=SwapHalf(val);
 }
 
/* test2() */  

void test2()
 {
  static volatile unsigned short val[2]={0x1111,0x2222};
  
  unsigned short temp=val[1];
  
  val[1]=val[0];
  val[0]=temp;
 }
 
/* Run<func>() */ 

template <void (*func)()> 
void Run(const char *name)
 {
  uint64 result=uint64(-1);
 
  for(unsigned n=1000; n ;n--)
    {
     uint64 start=CPUClock();
     
     for(unsigned k=1000; k ;k--) func();
     
     uint64 stop=CPUClock();
     
     stop-=start;
     
     if( stop<result ) result=stop;
    }
    
  printf("%s result = %llu\n",name,result);  
 }
 
/* Run2() */  

void Run2()
 {
  uint64 result=uint64(-1);
 
  for(unsigned n=1000; n ;n--)
    {
     uint64 start=CPUClock();
     
     static volatile unsigned short val[2]={0x1111,0x2222};
     
     __asm {
                mov ecx, 1000
            L:    
                sub ecx,1
                
                mov dx, WORD PTR val[0]
                mov ax, WORD PTR val[2]
                mov WORD PTR val[2], dx
                mov WORD PTR val[0], ax
                
                jne L
           }
     
     uint64 stop=CPUClock();
     
     stop-=start;
     
     if( stop<result ) result=stop;
    }
    
  printf("asm swap result = %llu\n",result);  
 }
 
/* main() */   

int main()
 {
  Run<&test1>("rot16");
  Run<&test1>("rot16");
  Run<&test2>("swap");
  Run<&test2>("swap");
  
  Run2();
  Run2();
 
  return 0;
 }


Вот результирующий ассемблер.

test2:

    call    ?CPUClock@@YA_KXZ            ; CPUClock
    mov    esi, eax
    mov    edi, edx

; 53   :      
; 54   :      for(unsigned k=1000; k ;k--) func();

    mov    ecx, 1000                ; 000003e8H
    npad    15
$LL4@Run@2:
    sub    ecx, 1
    mov    ax, WORD PTR ?val@?1??test2@@YAXXZ@4RCGC+2
    mov    dx, WORD PTR ?val@?1??test2@@YAXXZ@4RCGC
    movzx    eax, ax
    mov    WORD PTR ?val@?1??test2@@YAXXZ@4RCGC+2, dx
    mov    WORD PTR ?val@?1??test2@@YAXXZ@4RCGC, ax
    jne    SHORT $LL4@Run@2

; 55   :      
; 56   :      uint64 stop=CPUClock();

    call    ?CPUClock@@YA_KXZ            ; CPUClock


test1:

    call    ?CPUClock@@YA_KXZ            ; CPUClock
    mov    esi, eax
    mov    edi, edx

; 53   :      
; 54   :      for(unsigned k=1000; k ;k--) func();

    mov    ecx, 1000                ; 000003e8H
$LL4@Run:
    mov    eax, DWORD PTR ?val@?1??test1@@YAXXZ@4IC
    rol    eax, 16                    ; 00000010H
    sub    ecx, 1
    mov    DWORD PTR ?val@?1??test1@@YAXXZ@4IC, eax
    jne    SHORT $LL4@Run

; 55   :      
; 56   :      uint64 stop=CPUClock();

    call    ?CPUClock@@YA_KXZ            ; CPUClock


asm

    call    ?CPUClock@@YA_KXZ            ; CPUClock
    mov    esi, eax
    mov    edi, edx

; 75   :      
; 76   :      static volatile unsigned short val[2]={0x1111,0x2222};
; 77   :      
; 78   :      __asm {
; 79   :                 mov ecx, 1000

    mov    ecx, 1000                ; 000003e8H
$L$1444:

; 80   :             L:    
; 81   :                 sub ecx,1

    sub    ecx, 1

; 82   :                 
; 83   :                 mov dx, WORD PTR val[0]

    mov    dx, WORD PTR ?val@?3??Run2@@YAXXZ@4RCGC

; 84   :                 mov ax, WORD PTR val[2]

    mov    ax, WORD PTR ?val@?3??Run2@@YAXXZ@4RCGC+2

; 85   :                 mov WORD PTR val[2], dx

    mov    WORD PTR ?val@?3??Run2@@YAXXZ@4RCGC+2, dx

; 86   :                 mov WORD PTR val[0], ax

    mov    WORD PTR ?val@?3??Run2@@YAXXZ@4RCGC, ax

; 87   :                 
; 88   :                 jne L

    jne    SHORT $L$1444

; 89   :            }
; 90   :      
; 91   :      uint64 stop=CPUClock();

    call    ?CPUClock@@YA_KXZ            ; CPUClock


Такты

rot16 result = 6132
rot16 result = 6132
swap result = 6264
swap result = 6276
asm swap result = 6036
asm swap result = 6048
Для продолжения нажмите любую клавишу . . .

В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[8]: Умный вопрос по C/C++
От: Megabyte Россия  
Дата: 26.08.07 15:47
Оценка:
On Thu, 23 Aug 2007 12:49:03 +0600, Smal <54740@users.rsdn.ru> wrote:

> void swap_words3(uint32_t* arg)

> {
> union { uint16_t sp[2]; uint32_t v; } u;
> u.v = *arg;
> uint16_t hi = u.sp[0];
> uint16_t lo = u.sp[1];
>
> u.sp[1] = hi;
> u.sp[0] = lo;
> *arg = u.v;
> }

> Комментарии?


если я не ошибаюсь, запихивать в один член юниона, а вытаскивать из
другого (и наоборот) — тоже неправильно.

--
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
Posted via RSDN NNTP Server 2.0
Re[4]: Умный вопрос по C/C++
От: Lorenzo_LAMAS  
Дата: 27.08.07 07:24
Оценка:
Здравствуйте, elcste, Вы писали:

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


E>>Насколько я понимаю, в C++ стандарте такого ограничения нет. Тем не менее, GCC 3.4.4 для C++ генерирует такой же проблемный код, как и для C


E>В C++ все ровно то же самое.


E>

5.17/8 If the value being stored in an object is accessed from another object that overlaps in any way the storage of the first object, then the overlap shall be exact and the two objects shall have the same type, otherwise the behavior is undefined.


Возможно, я неправильно Вас понял, но мне кажется, что цитата относится к такому:
a = b; где b overlaps a: т.е. "the first object" и "an object" это а. А в оригинальном вопросе, ИМХО, подойдет лучше 3.10/15
Of course, the code must be complete enough to compile and link.
Re: Умный вопрос по C/C++
От: MasterZiv СССР  
Дата: 27.08.07 11:11
Оценка:
McSeem2 пишет:

> void swap_words(uint32_t* arg)

> {
> uint16_t* sp = (uint16_t*)arg;
> uint16_t hi = sp[0];
> uint16_t lo = sp[1];

В последних 3 строках считается, что это — big endien платформа.
Я не знаю, как там это называется с точки зрения стандарта, но
это — просто неправильно.
Posted via RSDN NNTP Server 2.1 beta
Re: Умный вопрос по C/C++
От: iiice Россия  
Дата: 04.04.08 09:11
Оценка: :)
Так работает:

#include <stdio.h>
#include <stdint.h>


#pragma pack(push, 2)
union un32
{
    uint32_t u32;
    struct
    {
        uint16_t u16_low;
        uint16_t u16_high;
    } u16x2;
};
#pragma pack(pop)

void swap_words(uint32_t* arg)
{
    union un32 *pu = (union un32*)arg;
    uint16_t  hi = pu->u16x2.u16_high;
    uint16_t  lo = pu->u16x2.u16_low;
    pu->u16x2.u16_low  = hi;
    pu->u16x2.u16_high = lo;
}

int main()
{
   uint32_t v1 = 0xFFFF0000u;
   uint32_t v2 = 0xFFFF0000u;

   swap_words(&v2);

   printf("%08X %08X\n", v1, v2);
   return 0;
}
Re: Умный вопрос по C/C++
От: Аноним  
Дата: 04.04.08 12:16
Оценка: -1 :)
Здравствуйте, McSeem2, Вы писали:
...
MS>Вопрос такой — что не так в этой программе? Подсказка — здесь имеется Undefined Behavior. Вопрос — Где?
...
MS>Это не глюк компилятора, компилятор ведет себя совершенно корректно. Просьба к гуру — подождать пару дней с ответом, чтобы любопытные, но менее опытные попытались сами докопаться до истины. А потом я хочу задать дополнительные вопросы, возникшие в связи с этим.

Что я могу сказать, за такие стандарты и компиляторы расстреливать надо. Недостатки аппаратуры выдавать за стандарт это не просто глупость. Куда мы катимся?! И это на обычных скалярных процессорах, а что же на векторных будет. Выравнивали бы по 64байта.
И вообще тенденция не здоровая аппаратные проблемы сваливать на программистов, причем в такой извращенной форме. Это ж не вам ассемблер.
А если в конкретной реализации процессора команда умножения не будет работать для умножения на 10. Это тоже попадёт в стандарт? типа a*=10; -- нелегально, опасайтесь такого кода и пишите так: a=a+a+a+a+a+a+a+a+a+a; а еще лучше так: std::algotithms::align_safe_assign(a, std::algorithms::safe_multiply( a, reiterpret_cast<std::typeof(a).type>10UUL ));

Такой C++ нам не нужен!

ps: #define true false // удачной отладки
Re[2]: Умный вопрос по C/C++
От: remark Россия http://www.1024cores.net/
Дата: 04.04.08 12:22
Оценка:
Здравствуйте, Аноним, Вы писали:

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

А>...
MS>>Вопрос такой — что не так в этой программе? Подсказка — здесь имеется Undefined Behavior. Вопрос — Где?
А>...
MS>>Это не глюк компилятора, компилятор ведет себя совершенно корректно. Просьба к гуру — подождать пару дней с ответом, чтобы любопытные, но менее опытные попытались сами докопаться до истины. А потом я хочу задать дополнительные вопросы, возникшие в связи с этим.


А>Что я могу сказать, за такие стандарты и компиляторы расстреливать надо. Недостатки аппаратуры выдавать за стандарт это не просто глупость. Куда мы катимся?! И это на обычных скалярных процессорах, а что же на векторных будет. Выравнивали бы по 64байта.

А>И вообще тенденция не здоровая аппаратные проблемы сваливать на программистов, причем в такой извращенной форме. Это ж не вам ассемблер.


Если ты не в курсе, то С/С++ изначально был и назывался как "портабельный ассемблер".
В С++ добавлили некоторые высокоуровневые конструкции, но суть никак не меняли.


А>Такой C++ нам не нужен!



Никто никого и не заставляет...



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[7]: Умный вопрос по C/C++
От: Erop Россия  
Дата: 04.04.08 12:35
Оценка:
Здравствуйте, remark, Вы писали:

E>>Ну, например, если железо фиксирует endian, то ты, читая int как коллекцию char получаешь уже вполне определённое поведение...


R>Показательный пример ты можешь видеть в первом посте этого топика


К char* приводить вроде как законно...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Умный вопрос по C/C++
От: Аноним  
Дата: 04.04.08 13:24
Оценка:
Здравствуйте, remark, Вы писали:

...
R>Если ты не в курсе, то С/С++ изначально был и назывался как "портабельный ассемблер".
R>В С++ добавлили некоторые высокоуровневые конструкции, но суть никак не меняли.
Ага поэтому его стремятся сделать всё мене портабельным.
Да конешно пусть компилятор умеет обращаться с жуткими абстракциями, но не умеет делать примитивные операции типа борьбы с выравниванием, а взваливает всё с чем было лень бороться разработчикам компилятора на конечных пользователей этого самого компилятора, а ещё лучше включить это в стандарт, чтобы было чем оправдываться. Зачем создавать проблемы на ровном месте? Я вот не понимаю это стремление к сексу стоя в гомоке.

А>>Такой C++ нам не нужен!

R>Никто никого и не заставляет...
Еще как заставляет
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.