Здравствуйте, GarryIV, Вы писали:
GIV>сорри в первый раз ошибка закралась — правильно так
GIV>задачка из третьего издания Страуструпа (§6.6 задача 15)
GIV>
GIV>void send(int *to,int *from,int count)
GIV>{
GIV> int n = (count+7)/8;
GIV> switch(count%8)
GIV> {
GIV> case 0: do{ *to++ = *from++;
GIV> case 7: *to++ = *from++;
GIV> case 6: *to++ = *from++;
GIV> case 5: *to++ = *from++;
GIV> case 4: *to++ = *from++;
GIV> case 3: *to++ = *from++;
GIV> case 2: *to++ = *from++;
GIV> case 1: *to++ = *from++;
GIV> } while(--n>0);
GIV> }
GIV>}
GIV>
GIV>второй день покоя не дает.
Я конечно могу ошибаться, но кажется что-то типа разворачивания цикла... ускоряет его исполнение.
Здравствуйте, GarryIV, Вы писали:
GIV>сорри в первый раз ошибка закралась — правильно так
ошибки бывают у всех без исключения, только у всех разные разной степени важности — это опыт, сын ошибок трудных.
GIV>задачка из третьего издания Страуструпа (§6.6 задача 15)
тут для пущей ясности стоит обратить еще внимание на упражнение номер 9.
не скрою. очень стало интересно, потому что Страуструпа вроде бы прочитал, но примера не помню.
Но вроде бы понял суть. Конечно же и я могу ошибаться, но надеюсь не сильно Это я сам себя подбадриваю.
void send(int *to,int *from,int count)
{
//количество проходов цикла - +7 я рассматриваю только как округление в большую сторонуint n = (count+7)/8;
//остаток от деления. понятно что значений может быть только 8 от 0 до 7
//раз все перечислены, то понятно, что обойти этот блок не удастся.
//насчет цикла - здесь ускорение может произойти разве что на первом вхождении и то если count%8 не равен нулю.
//case - это не что иное как метка, поэтому степень вложения значения не имеет. разве что если while(--n>0) написать в начале,
// то мы сделаем одну лишнюю итерацию, если count не будет кратен 8.switch(count%8)
{
case 0: do{ *to++ = *from++;
//вот тут мы и подошли к самому главному. в 9-ом упражнении он явно просит правильно расставить приоритеты
//выполнения операций, потому что при такой записи могут быть проблемы, если не учесть оные. Потому что согласно принятым стандартом приоритетами выполнения операций
//сначала будет инкрементирован указатель, а потом будет разыменован и по адресу на который указывает будет занесено значение. по этому (*XXX), а потом все остальное, но в принципе все по желанию.
//при данной конструкции кода если количество операций не очень велико, то просто произойдет присвоение (*to)=(*from) по внешним переданным адресам,
//но все равно CRT в конце концов свалится, потому что если в начале после int n = count%8; не сделать to = new int[n+8]; то стек потока будет нарушен
//если сделать еще один финт хвостом типа просто *++to = *from++;, то внешние переменные не изменят значений, а зрачки у нас потом в размерах все равно вырастут.case 7: *to++ = *from++;
case 6: *to++ = *from++;
case 5: *to++ = *from++;
case 4: *to++ = *from++;
case 3: *to++ = *from++;
case 2: *to++ = *from++;
case 1: *to++ = *from++;
} while(--n>0);
}
}
надеюсь ничего не забыл. Он спрашивает о том, кому может понадобиться такой код. Именно такой даже не знаю, а после некоторых не сложных преобразований кому угодно. фамилий называть не буду.
GIV>второй день покоя не дает.
желаю спокойствия и умиротворения.
Здравствуйте, Alexmoon, Вы писали:
A>Здравствуйте, GarryIV, Вы писали:
GIV>>сорри в первый раз ошибка закралась — правильно так A>ошибки бывают у всех без исключения, только у всех разные разной степени важности — это опыт, сын ошибок трудных.
Спасибо за поддержку
A>надеюсь ничего не забыл. Он спрашивает о том, кому может понадобиться такой код. Именно такой даже не знаю, а после некоторых не сложных преобразований кому угодно. фамилий называть не буду.
То как это безобразие работает вопросов как раз не вызывает — я даже для проверки набил и проверил себя. А вот зачем (кому) такое может понадобится? Меня смущает прыжок внутрь цикла. ИМХО это только затрудняет понимание текста и не имеет никаких преимуществ перед простым циклом.
while(--k>0) *to++=*from++;
Некоторое ускорение работы за счет развертывания цикла для меня не кажется весомым аргументом...
GIV>>второй день покоя не дает. A>желаю спокойствия и умиротворения. A>Удачи. Рад был помочь, если был прав.
И все таки в какой реальной ситуации подобный код может применяться? Или какой ответ имел ввиду Страуструп задавая этот вопрос?
PS: Я как то в школе написал похожую конструкцию на фокале (прикололся) — препод долго чесал репу, поставил "5" а остальным сказал чтоб не смели так писать.
Здравствуйте, Андрей Тарасевич, Вы писали:
GIV>>задачка из третьего издания Страуструпа (§6.6 задача 15)
.... АТ>Развертка цикла. Делается для оптиизации критического по времени выполнения кода.
Да Вы оказались правы это может сильно ускорить выполнение.
Здравствуйте, GarryIV, Вы писали:
GIV>То как это безобразие работает вопросов как раз не вызывает — я даже для проверки набил и проверил себя. А вот зачем (кому) такое может понадобится? Меня смущает прыжок внутрь цикла. ИМХО это только затрудняет понимание текста и не имеет никаких преимуществ перед простым циклом. GIV>
GIV>while(--k>0) *to++=*from++;
GIV>
Там break не стоит. И вообще не понятно, как этот код исполняется. Ведь, если count%8 != 0, то исполнение прыгает в цикл do минуя его (do)
Здравствуйте, King! Вы писали:
KO> Здравствуйте, GarryIV, Вы писали:
GIV>> То как это безобразие работает вопросов как раз не вызывает — я даже GIV>> для проверки набил и проверил себя. А вот зачем (кому) такое может GIV>> понадобится? Меня смущает прыжок внутрь цикла. ИМХО это только GIV>> затрудняет понимание текста и не имеет никаких преимуществ перед GIV>> простым циклом.
while(--k>0) *to++=*from++;
KO> Там break не стоит. И вообще не понятно, как этот код исполняется. KO> Ведь, если count%8 != 0, то исполнение прыгает в цикл do минуя его KO> (do)
Не нужен там break вот он и не стоит — этот код копирует count int'ов из одного массива в другой (аномалию при count<=0 не рассматриваем, Страуструп специально ошибки допускает в примерах). А do это всего лишь метка. Можешь сам скопировать да прогнать под отладчиком + посмотреть на asm.
GIV>То как это безобразие работает вопросов как раз не вызывает — я даже для проверки набил и проверил себя. А вот зачем (кому) такое может понадобится? Меня смущает прыжок внутрь цикла. ИМХО это только затрудняет понимание текста и не имеет никаких преимуществ перед простым циклом. GIV>
GIV>while(--k>0) *to++=*from++;
GIV>
GIV>Некоторое ускорение работы за счет развертывания цикла для меня не кажется весомым аргументом...
Именно ускорение, и это может быть весомым аргументом. В простом случае проверка и прыжок выполняется после пересылки каждого байта, а в примере — после каждого восьмого байта. Как сейчас — не знаю, а в старых процессорах (помните — там еще очередь команд чистилась после каждого джампа ) ускорение было значительным.
Здравствуйте, kulentsov! Вы писали:
GIV>> То как это безобразие работает вопросов как раз не вызывает — я даже GIV>> для проверки набил и проверил себя. А вот зачем (кому) такое может GIV>> понадобится? Меня смущает прыжок внутрь цикла. ИМХО это только GIV>> затрудняет понимание текста и не имеет никаких преимуществ перед GIV>> простым циклом.
while(--k>0) *to++=*from++;
Некоторое GIV>> ускорение работы за счет развертывания цикла для меня не кажется GIV>> весомым аргументом... k> Именно ускорение, и это может быть весомым аргументом. В простом k> случае проверка и прыжок выполняется после пересылки каждого байта, а в k> примере — после каждого восьмого байта. Как сейчас — не знаю, а в старых k> процессорах (помните — там еще очередь команд чистилась после каждого k> джампа ) ускорение было значительным.
Да, я уже провел тесты — в определенных ситуациях существенно быстрее.
Posted via RSDN NNTP Server 1.7 beta
WBR, Igor Evgrafov
Re: Зачем может понадобиться такой код?
От:
Аноним
Дата:
16.08.03 09:09
Оценка:
Здравствуйте, GarryIV, Вы писали:
GIV>сорри в первый раз ошибка закралась — правильно так
GIV>задачка из третьего издания Страуструпа (§6.6 задача 15)
GIV>
GIV>void send(int *to,int *from,int count)
GIV>{
GIV> int n = (count+7)/8;
GIV> switch(count%8)
GIV> {
GIV> case 0: do{ *to++ = *from++;
GIV> case 7: *to++ = *from++;
GIV> case 6: *to++ = *from++;
GIV> case 5: *to++ = *from++;
GIV> case 4: *to++ = *from++;
GIV> case 3: *to++ = *from++;
GIV> case 2: *to++ = *from++;
GIV> case 1: *to++ = *from++;
GIV> } while(--n>0);
GIV> }
GIV>}
GIV>