2013년 12월 16일 월요일

임베디드 프로그래밍 C코드 최적화 - 1


임베디드 프로그래밍 C코드 최적화를 읽고 정리...



임베디드 환경은 리소스가 부족하다.

여기서 리소스라 하면 메모리가 될수도 있고, CPU 성능이 될 수도 있고, 디스크의 남은 용량도 될수 있다.(요즘에는 라즈베리파이, 오드로이드 등등 조그만 고성능 보드들이 저가에 나오고 있지만 아직은 바로 바꿀것 같진 않다.)

그래서 메모리가 부족하거나, 디스크(롬)의 남은 용량이 부족하거나 하는 상황에 마주치고는 하는데 이를 위해 최적화가 필요한 것이다. x86이라면 굳이 해주지 않아도 될 정도의 리소스를 가지고 있어 굳이 최적화가 필요없다.


최적화의 방법들

1. 변수를 남발하기보다는 비트연산을 사용하자.
2. 포인터 없이 메모리에 접근할 수 있다.

 1
2
3
4
5
6
7
8
9
10
#define PA  (*(volatile unsigned char *)0x30000000)
int main (void)
{
    PA |= (0x7 << 5);
    return 0;
}

3. 컴파일러를 너무 믿지 말고 volatile 키워드를 쓰자.
    컴파일러가 똑똑하지만 우리는 컴파일러에게 속고 있을 수도 있다.
    volatile의 기능적 의미는 캐시사용안함이다. 보통 프로그램이 실행될 때 속도를 위해 필요한 데이터를 메모리에서 직접 읽어오지 않고 캐시로부터 읽어온다. 하지만, 하드웨어에 의해서 변경되는 값들은 캐시에 즉각적으로 반영되지 않으므로 데이터를 캐시로부터 읽어오지 말고 주 메모리에서 직접 읽어오도록 해야한다. 이러한 특성 때문에 하드웨어가 사용하는 메모리는 volatile로 선언해야 하드웨어에 의해 변경된 값들이 프로그램에 제대로 반영된다. - 

   이 키워드는 멀티코어 프로그래밍에서도 중요하게 사용되니 잊지 말자

4. 개발툴을 잘 이해하라.
   함수 호출 시 인자를 몇 개로 지정하는 것이 효과적인가는 컴파일러마다 다르므로 컴파일러를 잘 이해하는 것이 중요하다.


5. 포인터 체인을 제거하라

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
struct Point
{
    int x,y,z;
};
struct Obj
{
    Point *p1, *d;
};
void draw(struct Obj *a)
{
    a->p1->x = 0;
    a->p1->y = 0;
    a->p1->z = 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
struct Point
{
    int x,y,z;
  
};
struct Obj
{
    Point *p1, *d;
};
void draw(struct Obj * a)
{
    struct Point *k = a->p1;
    k->x = 0;
    k->y = 0;
    k->z = 0;
}
위쪽의 코드는 a를 접근할 때 매번 a를 다시 읽어오기 때문에 성능의 저하가 일어난다는 것이다.

6. register 변수를 활용해라.

7. 적절한 데이터 타입을 선택해라.
   데이터 버스는 데이터가 이동하는 통로이므로 데이터 버스의 폭은 프로세서에서 데이터를 한 번에 읽어오는 양과 직접적인 관계가 있다. 32비트 프로세서의 경우 데이터 버스의 폭이 4바이트이다. 이 프로세서에서 double형의 데이터를 메모리로부터 읽어오려면, double 데이터 타입의 크기가 8바이트이므로 4바이트의 버스 폭으로 데이터를 가져오려면 두번의 액세스가 필요하다. 그럼, 4바이트보다 작은 데이터 타입을 읽을때도 마찬가지로 효율성이 떨어진다. - 150P


http://kldp.org/node/79109
http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/C/Documents/COptimization
를 참고하면 더 좋은 이야기를 들을 수 있을 것이다.


2013년 12월 11일 수요일

임베디드 프로그래밍 C코드 최적화

저자 김유진




임베디드 환경에서의 개발은 이렇게 해야한다는 것을 보여주는 책으로 쉽게 설명되어 있다.

x86에서만 개발해 왔던 개발자들이 임베디드를 처음 접할 때 읽어보면 이해가 빠를 것 같다.

메모리를 아끼기 위한 비트조작이나, C를 충실히 해 왔어도 모를 최적화 팁. 포인터 활용 등은 한번 읽고 정리해 나가면 좋을 듯하다.

★★★★




2013년 11월 27일 수요일

갤럭시s3 젤리빈

어제 나온 젤리빈으로 업데이트했는데


사용하기 편하게 노티피케이션바에 NFC 읽고쓰고 기능이 추가된것 같았다.


하지만 문제는 티머니를 사용할 때 나왔다.


나는 버스카드를 주로 사용하고 카드가 없을 때만 갤3의 티머니를 사용한다.

뭐 다들 자주쓰는 지갑형 케이스를 사용하고 있어 NFC기능이 꺼졌는지 확인한다.

버스에서 내릴 때 버스카드를 찍었는데 순간 결재가 되더라...

놀라 확인해보니 모바일 티머니에서 빠져나간 것이었다.

집에 와 확인해보니 NFC를 켰을 때는 


그닥 변화없이 잘 쓰는듯했으나..


QT 기본 예제



QT로 GUI 작업을 할 때는 QT-Creator가 편하긴 한데

어찌된 일인지 QT + boost로는 QT-Creator에서는 자꾸 boost library 가 잘못되었는지 컴파일이 되지 않았다.

그래서 Visual Studio에서 작업을 하기로 했다.


새 프로젝트 추가



새 프로젝트를 Test01이라는 이름으로 만든다.


필요한 라이브러리를 체크


클래스 이름, 파일 이름 정하기




모두 끝내고 나면 솔루션 탐색기에는 대략 이렇게 구성될 것이다.

솔루션 탐색기


이대로 컴파일 하면 대략 요런 메세지가 뜬다.
1>Qt5Widgetsd.lib(Qt5Widgetsd.dll) : fatal error LNK1112: 'x64' 모듈 컴퓨터 종류가 'X86' 대상 컴퓨터 종류와 충돌합니다

뭐 대략 저번에 이 에러를 해결하는 방법을 써놨으나 포스팅을 찾는게 귀찮으신 분들을 위해 자세히 쓴다.


속성 페이지

대상 컴퓨터를 x86에서 x64로 바꾸어 주면 된다.
마찬가지로 컴파일 할때도 Win32가 아닌 x64로 바꾸어 준다.
못 찾는 분들이 있기에 친절하게 스크린샷을 남겨놓는다.


x64로 바꾸시라..!

그리고 컴파일을 해보면..!

뭐라는 거야..?



뭐 짧은 영어로 봤을때 Qt version을 바꿔달라는데... QT 옵션을 뒤지면 된다.

오른쪽 버튼을 클릭하자.

Qt Project Setting 창이 나올텐데
Version에서 자기가 설정한 버전으로 컴파일러를 선택해주자.

QT 버전을 선택하자.



그런 후 실행하면...

QT 기본 창



많은 준비를 한 것 치고는 아무것도 없는 심플한 창이 하나 생성되었다.

뭐 여기서 이깟 창하나 하는데 쓸데없이 길게 포스팅하냐고 하는 분들도 있겠지만

항상 처음인 사람들에게는 무언가 벽이 존재한다. 마찬가지로 프로그램에 익숙한 사람도 플랫폼이 달라지면, 사용하는 툴이 달라지면 별거 아닌 문제라고 생각되는것에 많은 시간을 투자하곤한다. 그런 벽을 조금이라도 낮게 해주고 싶어 이렇게 글을 남긴다. 뭐.. 나도 잘 까먹으니 나를 위해서라고 생각도 좀 되고 ^^


다음엔 boost 기본 예제랑 섞어서 진행할 예정이다.

2013년 11월 18일 월요일

Visual Studio 2012 + QT5.1 + Boost 환경에서 빌드하기


저번까지 Visual Studio2012에 QT5.1, Boost를 설치했었다.

내가 생각하는 구조는 Boost로 서버를 만들고, QT로 UI를 입히면 윈도우나 리눅스 어디서든 쓸 수 있을 거라 생각하고 포스팅을 한다.

환경 - AMD 페넘 960
OS - Windows7 64bit
IDE - Visual Studio 2012



저번에 Visual Studio에 QT를 설치했었다.
마찬가지로 Visual Studio에 Boost를 설치했었고..


헌데 이 두가지를 섞으면 링크 에러가 발생하였다.
뭐 boost랑 안맞는거 같은 느낌이 들어서 검색해보니 별놈의 해답들이 다 나오더라.. 그래서 이것저것 며칠동안 따라해봤는데 계속 같은 에러만 떴었다. 그러던 도중 오늘 답을 발견했다


boost를 다시 생성해보았다.

Visual Studio tool set -> x86 네이티브 커맨드를 켜고

b2 --toolset=msvc-11.0 architecture=x86 address-model=64 stage

amd는 address-model을 바꿔줘야 되나..???


참고해서 빌드했다.
http://lunapiece.net/Article/27356



그랬더니 링크에러는 사라지고 멀쩡하게 컴파일 되었다.

환경이 달라 다른 답이 있을거라 생각하지만 컴퓨터가 한대라 더 테스트 해 볼 수가 없다 ㅠ

나와 같은 문제점을 겪고 있는 다른사람에게 도움이 되길 ㅎㅎ

2013년 11월 13일 수요일

QT5.1 설치 및 Visual Studio 2012 Add-in 설치(Windows)

QT는 MFC와 같은 C++ 프레임워크이고 가장 장점으로는 크로스 플랫폼이라는 것이다.
예전부터 임베디드 환경에서 애용되고 있다. 오픈소스이지만 상용으로 사용할 때 라이센스가 다르므로 확인하고 넘어가도록 하자.


TrollTech -> nokia -> Digia 인수되었다.



환경
Windows7 Ultimate K  64bit
Visual Studio 2012  64bit ( update 3 )


1. http://qt-project.org/  에서 Qt 5.1.1 for Windows 64 - bit(VS 2012)를 다운받는다.

2. Visual Studio Add-in 1.2.2 for Qt5 를 다운받는다.

3. 1번에서 다운받은 파일을 설치한다.

4. 2번에서 다운받은 파일을 설치한다.

5. 내컴퓨터 -> 속성 -> 시스템 속성에서 환경변수를 추가한다.

6. 변수이름   QTDIR
    변수값      C:\Qt\Qt5.1.1\5.1.1\msvc2012_64;

7. Visual Studio를 켜서 QT5 탭으로 이동한다.

8. QT Option을 선택하여 QT Versions에 Add를 한다.

9. Version name    QT5.1
    Path  C:\Qt\Qt5.1.1\5.1.1\msvc2012_64

10. 설정해 주고 실행하면 LNK1112 에러가 난다. (x86과 x64가 다르다나..)

11. 프로젝트 속성 -> 링커 -> 고급 -> 대상컴퓨터 -> MachineX64로 바꾼다.

12. 그래도 실행하면 에러가 난다.(x64로 빌드가 되는지 확인한다)

13. 프로젝트 속성 -> Qt Project Settings 를 선택한다.

14. Properties탭에서 Version을 고른다.

15. 실행한다.





다음번엔 리눅스에서 설치해보려 한다.






2013년 9월 3일 화요일

boost 라이브러리 설치방법 ( 우분투 13.04, boost 1.53 )

1. 업데이트를 해준다.
    sudo apt-get update && sudo apt-get upgrade

2. 빌드에 필요한 구성요소를 설치해준다.
    sudo apt-get install build-essential
    sudo apt-get install python-dev
    sudo apt-get install libzip-dev
    sudo apt-get install libbz-dev

3. boost 홈페이지에서 버전에 맞게 받는다.

4. 압축을 풀어준다.
    tar xzvf boost_1_53_0.tar.gz

5. 압축을 푼 디렉토리를 /usr/local/ 에 위치시킨다.
   sudo mv boost_1_53_0/ /usr/local/

6. sudo ./bootstrap.sh를 실행한다.

7. bootstrap을 실행하면 bjam이라는 파일이 나온다.
   sudo ./bjam link=static stage




test.cpp
#include <boost/regex.hpp>
#include <iostream>
#include <string>

int main()
{
    std::string line;
    boost::regex pat( "^Subject: (Re: |Aw: )*(.*)" );

    while (std::cin)
    {
        std::getline(std::cin, line);
        boost::smatch matches;
        if (boost::regex_match(line, matches, pat))
            std::cout << matches[2] << std::endl;
    }
}

Makefile
CC=g++
CPPFLAGS=-O2 -I/usr/local/boost_1_53_0
LDFLAGS=-L/usr/local/boost_1_53_0/stage/lib

LDLIBS=-lboost_regex

all: test

clean:
rm -rf test
rm -rf *.o



7. make를 실행하여 컴파일이 잘 되었는지 확인한다.
    make

8. ldd test를 실행하여 이상이 없는지 확인한다.
   ldd test


9. ./test를 실행하면 대기상태로 나오는데 아래와 같이 입력한다.
입력 - Subject: Will Success Spoil Rock Hunter?
출력 - Success Spoil Rock Hunter?


10. makefile을 편하게 사용하기 위해 .bashrc파일을 수정한다.
original Makefile
CC=g++
CPPFLAGS=-O2 -I/usr/local/boost_1_53_0
LDFLAGS=-L/usr/local/boost_1_53_0/stage/lib
LDLIBS=-lboost_regex

all: test

clean:
rm -rf test
rm -rf *.o

.bashrc
# by gilgil

export CPPFLAGS="-I/usr/local/boost_1_53_0"
export LDFLAGS="-L/usr/local/boost_1_53_0/stage/lib"


modified Makefile
CC=g++
CPPFLAGS+=-O2
LDLIBS=-lboost_regex

all: test

clean:
rm -rf test
rm -rf *.o



출처 : . http://gilgil.net/?document_srl=7273
           http://threadbuilder.wordpress.com/2013/03/26/ubuntu-eclipse-boost-setting/
           http://gilgil.net/8563