2011. 1. 3. 15:34
c++ 자체가 개객기 라서 그렇습니다

컴파일러가 함수의 프로토 타입을 선언 한 것이라 보기 때문입니다.

그니까

class MyClass {
public:
   MyClass() {};
};

MyClass hello; //  hello 라는 객체를 선언합니다.
MyClass helloWorld(); // MyClass를 리턴하는 인자가 없는  helloWorld 함수의 프로토타입을 선언합니다.

이것을 함수 안에서  쓴다면 함수안에서 선언이 안되는 언어기에
prototyped function not called (was a variable definition intended?) 라고 컴파일러가 경고를 해줍니다.

그러나 전역 범위에서 쓴다면 경고도 안뛰워줍니다.

.... 보고 까먹고 또 찾고 보고 까먹고 또 찾고. c++은 너무 복잡혀...
Posted by newpolaris
2010. 12. 17. 00:22



void myPCA( CvMat* A, CvMat* U2 ) {
 CvMat* U  = ::cvCreateMat( A->rows, A->cols, A->type );
 CvMat* S  = ::cvCreateMat( A->cols, A->cols, A->type );
 functionFillMatrixUandS( A, S, U );

 // GOAL: Efficent way copy data from U to U2, Just like crop matrix U as size of U2
 // Matlab:  [ uy, ux ] = size(U);
 //              U2 = U( 1:uy, 1:ux ); % simple isn't it?
 
  // 1. Create header only matrix, if you give null matrix it cause error
 CvMat* header = ::cvCreateMatHeader( U2->width, U2->height, U2->type );
  // 2. Fill matrix 'header' with pointers which pointing each row start position in U element
  //    accessing matrix element are restricted width small size(resized matrix width),
  //    accessing next row restricted with U's step
  //    header matrix has U's step, U2's width
 ::cvGetSubRect( U, header, cvRect( 0, 0, U2->width, U2->height ) );
  // 3. Need hard copy, to survie without U matrix
 ::cvCopy( header, U2 );

 ::cvReleaseMat( &U );
 ::cvReleaseMat( &header );
 ::cvReleaseMat( &S );
}

note:

// Selects sub-array (no data is copied)
CV_IMPL  CvMat*
cvGetSubRect( const CvArr* arr, CvMat* submat, CvRect rect )
{
    /*
    int* refcount = mat->refcount;

    if( refcount )
        ++*refcount;

    cvDecRefData( submat );
    */
    submat->data.ptr = mat->data.ptr + (size_t)rect.y*mat->step +
                       rect.x*CV_ELEM_SIZE(mat->type);
    submat->step = mat->step;
    submat->type = (mat->type & (rect.width < mat->cols ? ~CV_MAT_CONT_FLAG : -1)) |
                   (rect.height <= 1 ? CV_MAT_CONT_FLAG : 0);
    submat->rows = rect.height;
    submat->cols = rect.width;
    submat->refcount = 0;
    res = submat;

    return res;
}

 

Posted by newpolaris
2010. 12. 16. 22:12


병신 같은 for문 처리 속도 빼문에 matlab이 느리다고 생각하게 되는데요,
( 그외로 여러가지 약점이 있지만...)

128,000 x 300 matrix를 서로 곱하여 봅시다.

openCV 나름대로 요즘 올라오는거 보면
"Blas 적용했음. 20% 속도 향상 기대함여" 등등이 있는데요,
  -  Matrix multiplication now is done by blocks resulting
90      in better cache utilization => better performance.
91      Optionally, gemm from Intel MKL can be used. (beta 4)
... 대충 코드 위치로 볼때 gemm에 blas 적용은 안된것 같음..


matlab ... 상용 라이브러리 + ublas + 미친듯한 튜닝 으로 0.7 sec를 보여줍니다.

테스트도 쉽습니다. 인터프리터에 rand 하고 * 기호 써서 곱합니다. 그걸 tic;toc으로 감싸주시면 됩니다.
>> tic; AtA = T'*T;toc;
Elapsed time is 0.557990 seconds.
>> tic;T = rand(128*1000, 300); AtA = T'*T; toc;
Elapsed time is 1.167132 seconds.
.....single으로 감싸도 별반 차이없습니다.

openCV 우선 한숨부터 쉬고...

프로젝트 만들고 인클루드하고
우선 timer용으로 쓸 함수 include 하고
openCV 세팅하고
결과를 보기위해 컴파일하고

돌립니다!

    enum { DESC = 128, NUM_DESC = 1000, NUM_PIC = 300 };
    CvMat* M = ::cvCreateMat( DESC * NUM_DESC, NUM_PIC, CV_32FC1 );

    my_pca::randn( M, 100, 20 );

    CvMat* AtA = ::cvCreateMat( NUM_PIC, NUM_PIC, CV_32FC1 );
    ::cvGEMM( M, M, 1.0, NULL, 0.0, AtA, CV_GEMM_A_T );

    ::cvReleaseMat( &M );
    ::cvReleaseMat( &AtA );

10 sec 나왔네요 감사합니다.

randn은 openCV rand함수 감싼건데요 단독으로 400ms 나옵니다.


ㅅㅂ......

결론 :  상용 library와 최적화로 무장한 matlab의 행렬 곱 연산은
           openCV에서 새롭게 적용된 blas 적용 곱하기에 비해 디지게 빠릅니다.



I think its because you are trying to multiply two matrices, which
is speciality of matlab. Its made for matrix operations, and its one
thing its is extremely difficult to beat matlab at.

matlab achieves this speed with matrices by using platform
customized packages for libear algebra namely blas and lapack and of
course lot of intelligent tweaks. If you look in matlab bin
directory you will find files like altas_PIII.dll, atlas_PIV.dll and
mkl_PIV.dll etc. these are the 3rd party packages matlab uses.

atlas is Automatically Tuned Linear Algebra Subroutines - it
contains blas and lapack. It is opensource project.

mkl is Maths Kernal Library which is again optimized implementation
of blas and lapack but is developed by intel so supposedly better.
but mkl is not free.

Now to be fair to opencv I would recommend you try some highlevel
function for example canny. Then you will know the speed difference.

-Saurabh

Posted by newpolaris
2010. 12. 14. 03:00

오목이든

오목이든 오델로든..

컴퓨터한테 이기는 방법 알려드릴까요? ㅎ

프로그램을 두개띄웁니다. 한쪽은 먼저하게 하고 다른쪽은 늦게 하게합니다.

먼저하는쪽의 컴이 두는걸 다른쪽에다가 바로 써먹습니다..ㅡ,.ㅜ;;

둘중한쪽은 이길겁니다. ^,.^

Posted by newpolaris
2010. 12. 9. 16:56

1번은 동시에(simultaneous)를 어떻게 처리해야 할지 모르것다.

해외 답을 봐도 '동시'에 실행하는 답은 없는 것 같은데 먼가 내가 핀트를 잘못잡고 있는듯,

머 어짜피 atomic이라 해도 erlang 내부에서 말이지, chapter 20.1을 보면
"등록된 프로세스를 만들때 마다 우리는 잠재적인 순차적 병목을 만들고 있다" 라고 적힌것을 보면 erlang 내부에서 적당히 처리해주는 것 같다. IO 쪽에서 이 내용이 나오느데 이걸 하드에도 기록하나;

머 하여간 2번 문제는 적당히 풀었다. 

코드가 병렬화 되어 있지 않습니다. 수정한 버전은 나중에 올리겠습니다.

-module(erl8p2).
-export([main/2]).

makeRing(N) ->
    Pids = for(1,N, fun ringNode/0),
    LastElm = lists:last(Pids),
    [LastElm | Pids].

destroyRing(RingElmPids) ->
    [_|T] = RingElmPids,
    lists:foreach(fun(Pid) -> Pid ! die end, T).

ringNode() ->
    spawn(fun loop/0).

loop() ->
    receive
        {ring, [], _Request, Dest, _Result} ->
            % io:format("Last Node:~p ~p~n",[ring, Msg, pid_to_list(self())]);
            Dest ! {ring,_Result},
            loop();
        {ring, [H|T], Request, _Dest, _Result} ->
            % io:format("Received:~p to ~p~n",[ring, Msg, pid_to_list(H)]),
            H ! {ring, T, Request, _Dest, _Result},
            loop();
        die -> void
    end.          

for(N,N,Fun) -> [Fun()];
for(I,N,Fun) -> [Fun()|for(I+1,N,Fun)].
   
sendRingMsg(RingElmPids, Msg) ->
    [H|T] = RingElmPids,
    H ! {ring, T, Msg, self(), []},
    receive
        {ring, Results} -> Results
    end.                          

stopWatch(Fun) ->
    statistics(wall_clock),
    statistics(runtime),
    Fun(),
    {_, Time1} = statistics(wall_clock),
    {_, Time2} = statistics(runtime),
    [Time1, Time2].

main(N,M) ->
    RingElmPids = makeRing(N),
    [Time1, Time2] = stopWatch(fun() -> for(1,M, fun() -> sendRingMsg(RingElmPids, "Hello World") end) end),
    io:format("Ring benchmark tim = ~p (~p) ms~n", [Time1, Time2]),
    destroyRing(RingElmPids).
    
;; 결과는 아래와 같다.                    
21> erl8p2:main(10000,10).
Ring benchmark tim = 7894 (6896) ms

fun이 local function 보다는 느리고 apply보다는 빠른 연산이라고 하는데,
"2.1  Myth: Funs are slow"
http://www.erlang.org/doc/efficiency_guide/myths.html
나중에 fun이나 바꿔야할 것 같다.

...언제나 느끼는 것이지만 짧은 영어 실력에서 나오는 변수명은 참 눈물난다.
그 때문에 짧은 설명은 붙이자면,
makeRing, destoryRing은 ringNode라 불리는 (뒷부분에선 ringElm로 개명한다..?!)
각 ring을 구성하는 element들의 집합으로 구성되는데,
(나중에 고쳐야될 것 같지만) 1->2->3->1 로 끝부분이 이어지도록 구성된다.

끝부분이 이어진다고 먼가 좋은 것이 있는 것은 아니고 그 덕분에 함수 성질에따라
H를 날리거나 그대로 이용한다.
destoryRing은 같은 element를 2번 지우면 안되니까 Head를 뺀 2, 3, 4, 1을 삭제하고,
sendRingMsg은 Head 로 메시지를 보내 다시 Head로 돌아오도록 만들때 이용한다.

loop는 각 element가 실제로 일을 처리하는 넘인데,
Request에 따라 일을 처리하고 Response에 결과를 추가하고 다음 elements(Pids의 Head)로 전송하는 역활을 한다.
여기서는 하는 일이 없으니 걍 Msg 받고 다음 elements로 메시지를 보내는 역활만 한다.
 {ring, Pids, _Request, Dest, _Result}  는 대충 {ID, next Element Pids, Requtest, 마지막 결과 받을넘, 각노드의 결과}를 나타낸 Msg이다.

그니까
        {ring, [], _Request, Dest, _Result} ->
            Dest ! {ring,_Result},

next elemets Pids가 바닥난 한바퀴 돈 상황에서
Dest로 Results를 발신하고

그제서야 전체 Ring에 Request 를 보내 한바퀴 일 시키신
sendRingMsg께서는 결과를 받아보시고 종료한다.

------------------------------------------------------------------------------------------
수정본: spawn 한다음에 작업 마칠때 까지 기다려주려나? 메시지 통신으로 직접 알아야 하나?

-module(erl8p2).
-export([main/2]).

constructRing(N) ->
    Pids = for(1,N, fun ringNode/0),
    LastElm = lists:last(Pids),
    [LastElm | Pids].

destructRing(RingElmPids) ->
    [_|T] = RingElmPids,
    lists:foreach(fun(Pid) -> Pid ! die end, T).

ringNode() ->
    spawn(fun loop/0).

loop() ->
    receive
        {ring, [], _Request, Dest, _Result} ->
            % io:format("Last Node:~p ~p~n",[ring, Msg, pid_to_list(self())]);
            Dest ! {ring,_Result},
            loop();
        {ring, [H|T], Request, _Dest, _Result} ->
            % io:format("Received:~p to ~p~n",[ring, Msg, pid_to_list(H)]),
            H ! {ring, T, Request, _Dest, _Result},
            loop();
        die -> void
    end.          

for(N,N,Fun) -> [Fun()];
for(I,N,Fun) -> [Fun()|for(I+1,N,Fun)].
   
sendRingMsg(RingElmPids, Msg) ->
    [H|T] = RingElmPids,
    H ! {ring, T, Msg, self(), []},
    receive
        {ring, Results} -> Results
    end.                          

timer(start) ->
    statistics(wall_clock),
    statistics(runtime);

timer(stop) ->
    {_, Time1} = statistics(wall_clock),
    {_, Time2} = statistics(runtime),
    [Time1, Time2].

messageRing(RingElmPids) ->
    spawn(fun() -> sendRingMsg(RingElmPids, "Hello World") end).
 
main(N,M) ->
    RingElmPids = constructRing(N),
    timer(start),
    for(1, M, fun() -> messageRing(RingElmPids) end),
    [Time1, Time2] = timer(stop),
    io:format("Ring benchmark tim = ~p (~p) ms~n", [Time1, Time2]),
    destructRing(RingElmPids).

49> erl8p2:main(10000,1000).
Ring benchmark tim = 281 (297) ms

sendRingMsg(RingElmPids, Msg) ->
    [H|T] = RingElmPids,
    H ! {ring, T, Msg, self(), []},
    receive
        {ring, Results} -> Results
    end.    

Posted by newpolaris
2010. 12. 5. 20:29

msys의 bash는 뭐 알아서 잘해주더라 그런 이야기다.
/usr/bin/에 env.exe란 파일로 존대한다. 그러므로

#!/usr/bin/env escript라 써도 잘해석하고 잘 해준다.
책에는 저자가 난 모르오 누군가 갈켜 주시오 그리 되어있는데 escript.exe도 존재하니
msys없이도 그냥 호출하면 될 듯하다.

옵션은 아래와 같이 먹일 수 있다고 하네;
#!/usr/bin/env escript
%% -*- erlang -*-
%%! -smp enable -sname factorial -mnesia debug verbose
http://www.erlang.org/doc/man/escript.html

평소에 자주쓰는 #! 구문은 도대체 무었인지 좀 찾아봤다.
그 녀석은 "Shebang" 으로 불리는데 (hashbang, hashpling, pound bang, or crunchbang)

#! 다음 부터는 program loader가 첫줄의 나머지 부분을 interpreter directive로 보고 파싱해서 그 해당하는 넘을 첫줄에 있는 옵션과 함께 잘 실행 시켜 준다고 한다.

(when it occurs as the first two characters in the first line of a text file. In this case, the program loader in Unix-like operating systems parses the rest of the first line as an interpreter directive and invokes the program specified after the character sequence with any command line options specified as parameters.) http://en.wikipedia.org/wiki/Shebang_(Unix)

그런대 왜 #! /usr/bin/env python도 동작 되느냐 하면, env라는 프로그램이 $PATH를 검사해서 python을 찾아준다고 한다.
( At least on the operating systems I have checked, #! must be followed by
the full pathname of a program. It does not search $PATH for it.
'/usr/bin/env python' searches $PATH for python and runs it.
(Usually env is used to set some environment variables for a program,
e.g. 'env PYTHONPATH=whatever python', but one need not specify any
environment variables
Since env is (almost?) always in /usr/bin, while python can be installed
God-knows-where, that is more portable than writing #!/local/bin/python
or #!/usr/bin/python or whatever..) http://www.velocityreviews.com/forums/t324727-what-does-usr-bin-env-python-do.html

가장 상세한 메뉴얼은 http://www.in-ulm.de/~mascheck/various/shebang/ 거 같은디
exec()가 수행한다고하네

      Some background.  When the UNIX kernel goes to run a program (one
      of the exec() family of system calls), it takes a peek at the
      first 16 bits of the file.  Those 16 bits are called a `magic
      number'.  First, the magic number prevents the kernel from doing
      something silly like trying to execute your customer database
      file.  If the kernel does not recognize the magic number then it
      complains with an ENOEXEC error.  It will execute the program only
      if the magic number is recognizable.

Posted by newpolaris
2010. 12. 5. 03:00

reference manual은,

( official )
http://erlang.org/doc/
( alternative )
http://erldocs.com/

이거고, 책에 예제 1줄 안비고 걍 넘어간 refernce는, 아래와 같따.

Refs

A ref (or reference) is a term which is unique, even across Erlang nodes. You can create a new ref by calling erlang:make_ref/0. A reference is only used as a unique tag or identifier. An Erlang reference should not be confused with a reference in C/C++.

2> erlang:make_ref().
#Ref<0.0.0.41>
Posted by newpolaris
2010. 12. 5. 02:56
함수 참조 (function reference)
그냥 module에 정의된 fuction을 사용할때 이렇게도 적을 수 있구나 정도로 받아들이면 되겠다.

fun LocalFunc/Arity

There are several ways to pass and call functions in erlang:

- to create a function closure (F) wrapping a segment of code in a erlang fun do:
F = fun(...Args...) -> ...Code... end

- or define a reference to a function:
F = foo/3
F = module:foo_function/2

- it is also possible to pass a function name or {module,function} tuple as mentioned in the article (although the tuple notation is only retained for backwards compatibility with ancient code).

To use a function reference one can simply call it as:

F = ...,
... = F(...),


or directly:

... = (fun(A) -> A * A end) (2),

... = (fun add/2) (2, 2),

... = (fun math:pow/2) (2, 2),

... = {math, pow} (2, 2),

Function and module names can be used the same way:

FunctionNameAtom = add,
... = FunctionNameAtom(2),

ModuleNameAtom = math,
FunctionNameAtom = pow,
... = ModuleNameAtom:FunctionNameAtom(2)


There are some rare cases when apply is useful, but it rare to see it in modern erlang code.


Posted by newpolaris
2010. 12. 4. 02:10
Programing erlang p.71

Most effient way to make a list. Insert into a head.

some_function([H|T], ..., Result, ...) ->
   H1 = ... H ...,
   some_function(T, ..., [H1 | Result ], ...);
some_function([], ..., Result, ...) ->
   {..., Result, ...}.

Use function lists:reverse to reverse Result(list).
Don't use operation ++ (ex: List ++ [H])

programming erlnag p.168
-module(ctemplate).
-compile(exprot_all).

start() ->
   spawn(fun() -> loop([]) end).

rpc(Pid, Request) ->
   Pid ! {self(), Request},
   receive
      {Pid, Response} ->
            Response
   end.

loop(X) ->
   receive
      Any ->
        io:format("Received:~p~n", [Any]),
        loop(X)
   end.

Use TDD strategy.
Use erlang shell as small steps on TDD.
Posted by newpolaris
2010. 12. 3. 14:56

% module

-module(eulerPro2).
-export([piboSum/1]).
   
isEven(N) ->
    even(N rem 2 =:= 0).
even(false) -> odd;
even(true) -> even.

piboSum(N) ->
    piboSum({1,1},{0,N},odd).

piboSum({A,B},{Sum,N},odd) when A =< N ->
    piboSum({B,A+B},{Sum,N},isEven(B));

piboSum({A,B},{Sum,N},even) when A =< N ->
    piboSum({B,A+B},{Sum+A,N},isEven(B));

piboSum({A,_},{Sum,N},_) when A > N ->
    Sum.


          
% test
-module(eulerPro2_tests).
-include_lib("eunit/include/eunit.hrl").

piboSum_test() ->
    ?assertEqual(0, eulerPro2:piboSum(1)),
    ?assertEqual(2, eulerPro2:piboSum(2)),
    ?assertEqual(2, eulerPro2:piboSum(5)),
    ?assertEqual(10, equerPro2:piboSum(8)).

   

Posted by newpolaris