Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > ОПТИМИЗАЦИЯ КОДА


Автор: _aleks_ 31.3.2005, 06:08
Может подскажет кто-нибудь как эту функцию можно ещё оптимизировать smile

Код

unsigned char func_grayscale(unsigned long int color)
{
    unsigned long int color;
    unsigned char grayscale;
    char *pb = (char *)&color;
    return (*pb)*0.11+(*(pb+1))*0.59+(*(pb+2)*0.3;
}


Автор: chipset 31.3.2005, 06:36
Начнём с того что он не компилируется, у тебя траблы со скобками, нужно так:
Код

return (*pb)*0.11+(*(pb+1))*0.59+(*(pb+2)*0.3);

Во-вторых не скомпилируется ибо:
Цитата
error C2082: redefinition of formal parameter 'color'
, и редифинишн color нужно выкинуть нафиг.
В-третьих, зачем указатель pb?, приходится раскрывать его всё время, что ест операции.
В-чётвёртых, зачем pb вообще если можно привести потом всё в конце static_cast'ом?
В-пятых, почему заголовок большими буквами?

Автор: Fire-Plug 31.3.2005, 07:34
_aleks_
Похоже, что тебе надо вычислить значение след.выражения:

1-й байт * 0.11+ 2-й байт * 0.59 + 3-й байт*0.3.

Что, кстати, закодировано в байтах color - RGB?
Итак, мне видится 2 подхода к решению:

1) union
Код

unsigned char grayscale(unsigned long nColor)
{
    union _COLOR
    {
        unsigned char chB[4];
        unsigned long nB;    

    } unColor;
    unColor.nB= nColor;

    return (unsigned char)(unColor.chB[0]*0.11 + unColor.chB[1]*0.59 + unColor.chB[2]*0.3); 
}

2) битовые операции
Код

unsigned char grayscale2(unsigned long nColor)
{
    unsigned char b1= (unsigned char)( nColor & 0xFF);
    unsigned char b2= (unsigned char)((nColor & 0xFF00) >> 8);
    unsigned char b3= (unsigned char)((nColor & 0xFF0000) >> 16);

    return (unsigned char)(b1*0.11 + b2*0.59 + b3*0.3); 
}

Следует иметь в виду, что тип результата выражения - double, хоть и множество его значений находится в пределах [0...255].
Ну что с ним делать уже решать тебе.

Автор: _aleks_ 31.3.2005, 15:18
Дело в том что надо, чтобы функция выполнялась как можно быстрее, поэтому я подумал что если арифметические операции будут выполняться паралельно то время выполнения уменьшиться smile

Код


unsigned char func_grayscale(unsigned long int color)
{
    unsigned long int color;
    unsigned char grayscale, r, g ,b;
    char *pb = (char *)&color;
    b=(*pb)*0.11;
    g=(*(pb+1))*0.59;
    r=(*(pb+2))*0.3;
    return r+g+b;
}

Автор: oleg1973 31.3.2005, 16:09
маразм однако, вот где индейцы побеждают smile
Код

int super(color)
{
    int result;

    _asm
    {
            mov ecx,color
            movzx eax,cl
            mov edx,0x3de147ae //0.11
            mul edx
            mov ebx,eax

            movzx eax,ch
            mov edx,0x3f170a3d //0.59
            mul edx
            add ebx,eax

            shr ecx,16

            movzx eax,cl
            mov edx,0x3e99999a //0.3
            mul edx
            add ebx,eax
            mov result,ebx

    }
    return result;
}

Автор: cardinal 31.3.2005, 16:20
А если еще учесть, что
Код

    b=(*pb)*0.11;
    g=(*(pb+1))*0.59;
    r=(*(pb+2))*0.3;

и
Код

    b=(*pb)*0.125; // << 3
    g=(*(pb+1))*0.5; // << 1
    r=(*(pb+2))*0.375; // << 3) * 3

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

Автор: Fixin 31.3.2005, 17:24
Хороший вариант у oleg1973 (естественно smile), но тормозны операции с плавучей точкой. Там их три, а можно сделать одну:
Код
b=(*pb)*11;
g=(*(pb+1))*59;
r=(*(pb+2))*30;
return (unsigned char)((r+g+b)/100);

Автор: maxim1000 31.3.2005, 17:38
делить вообще не стоит smile
вместо 100 можно взять степень двойки, тогда можно будет просто сдвинуть...

Автор: cardinal 31.3.2005, 17:38
Fixin, посмотри что я написал smile

Автор: En_t_end 31.3.2005, 17:40
Если уж такая тема, то и мне помогите, но у меня скорее задача решена правильно, но как всегда по-тупому smile
ЗЫ просьба не пинать smile
Код

//Программа для игры "камень-бумага-ножницы".
//R - камень
//P - бумага
//S - ножницы
#include "stdafx.h"
#include "iostream"
using namespace std;

void main(){
    char player1;
    char player2;
    cout << "First player, enter you argument. R(r) or P(p) or S(s).\n";
    cin >> player1;
    system("cls");
    cout << "Second player, enter you argument. R(r) or P(p) or S(s).\n";
    cin >> player2;
    switch(player1){
        case 'p':
        case 'P':
            switch(player2){
        case 'r':
        case 'R':
            cout << "Player1 - You WON!!!\n";
            break;
        case 's':
        case 'S':
            cout << "Player2 - You WON!!!\n";
            break;
        default:
            cout << "Player1 - Not won...Player2 - Not won.\n";
            }
            break;
                    
        case 'r':
        case 'R':
            switch(player2){
        case 's':
        case 'S':
            cout << "Player1 - You WON!!!\n";
            break;
        case 'p':
        case 'P':
            cout << "Player2 - You WON!!!\n";
            break;
        default:
            cout << "Player1 - Not won...Player2 - Not won.\n";
            }
            break;

        case 's':
        case 'S':
            switch(player2){
        case 'p':
        case 'P':
            cout << "Player1 - You WON!!!\n";
            break;
        case 'r':
        case 'R':
            cout << "Player2 - You WON!!!\n";
            break;
        default:
            cout << "Player1 - Not won...Player2 - Not won.\n";
            }
            break;
    }

//    P > R R > S S > P
}

Автор: Fixin 31.3.2005, 17:40
Цитата(cardinal @ 31.3.2005, 17:38)
Fixin, посмотри что я написал smile

Ага, угу, ну да. Но так понятнее smile

Автор: oleg1973 31.3.2005, 17:47
Fixin
Цитата
но тормозны операции с плавучей точкой

а где они там у меня?
там простое умножение без FPU

Автор: maxim1000 31.3.2005, 17:47
Цитата
Если уж такая тема, то и мне помогите, но у меня скорее задача решена правильно, но как всегда по-тупому
ЗЫ просьба не пинать

ну все-таки тема чужая smile

Код

char Array[3]={'r','p','s'};
char CharToLow(char x)//знаю, что есть такая функция, вспоминать лень...
{
  if(x<'A')
    return x;
  if(x>'Z')
    return x;
  return x-'A'+'a';
}
void main()
{
  char player1,player2;
  int n;
  //get players input
  //...
  player1=CharToLow(player1);
  player2=CharToLow(player2);
  for(n=0;n<3;n++)
  {
    if(Array[n]==player1)
      break;
  }
  if(n==3)
  {
    cout<<"RTFM!..\n";
    return;
  }
  if(player2==Array[(n+1)%3])
    cout<<"player2 won\n";
  else
    cout<<"player1 won\n";
}

Автор: Doc_d0s 31.3.2005, 17:53
Код

unsigned char func_grayscale(unsigned long int color)
{
    unsigned long int color;////!!!!!! тут не надо переопределять color
    unsigned char grayscale;// а зачем он тут нужен?:)
    char *pb = (char *)&color;
    return (*pb)*0.11+(*(pb++))*0.59+(*(pb++)*0.3;
}


Вот такsmile)

Автор: En_t_end 31.3.2005, 17:56
maxim1000 
Верно !
Но вот только тут одна проблема smile, я по книжке ещё ламо и там не предполагается, что я знаю массивы и соответственно операции над ними. ЗЫ так что мне наверное придется так и остаться со своим тупым свичем smile

Автор: sergejzr 31.3.2005, 17:58
ИМХО для geyscale вариант Cardinala рулит smile Не банковские же проценты вычислять smile
А если точность нужна, то Fixin'a вариант smile

Сколько тактов надо для умножения с пл. точкой? около 80?
На сдвиг думаю 1-3, на умножение целых чисел 32...

Автор: maxim1000 31.3.2005, 18:02
эх...работал я как-то на сигнальном процессоре Blackfin...если не использовать специальные инструкции для обработки видео, то там это делается приблизительно так:
Код

  a0=0;
  //red
  r1=r0.b(z);
  r2=((11<<16)/100);//не пугайтесь, это для препроцессора :)
  a0+=r1*r2(is);
  //green
  r0>>=8;
  r1=r0.b(z);
  r2=((59<<16)/100);
  a0+=r1*r2(is);
  //blue
  r0>>=8;
  r1=r0.b(z);
  r2=((30<<16)/100);
  a0+=r1*r2(is);
  r0>>=8;
  //result
  r0=a0;
  r0>>=16;

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

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)