Help us understand the problem. What is going on with this article?

main関数を再帰呼び出しする

More than 1 year has passed since last update.

たまたまmain関数を再帰呼び出しするって見たので、普通の人はmain関数の関数を再帰呼び出しするんだろうけど、プロセス起動しちゃったらどうなるんだろうかとフィボナッチ数列でやってみた。

普通にプロセス起動

ほとんどWin32のサンプルを見ながら作ったけど、なんでCreateProcessって無駄に引数が多いのだ!

int exec(int n)
{
    STARTUPINFO         si = { 0 };
    PROCESS_INFORMATION pi = { 0 };
    char cmd[1024];
    sprintf_s(cmd, "fib.exe ? %d", n);
    CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
    WaitForSingleObject(pi.hProcess, INFINITE);
    DWORD rc;
    GetExitCodeProcess(pi.hProcess, &rc);
    printf("%s rc=%d\n", cmd, rc);
    n = rc;
    return n;
}

int main(int argc, char **argv)
{
    int n = 0;
    if (argc == 2) {
        n = atoi(argv[1]);
    } else if (argc == 3) {
        n = atoi(argv[2]);
    }
    if (n >= 2) {
        n = exec(n - 2) + exec(n - 1);
    }
    if (argc == 2) {
        printf("%d\n", n);
    }
    return n;
}

VC2017でfib.exeってビルドする。

> fib.exe 5
fib.exe ? 1 rc=1
fib.exe ? 0 rc=0
fib.exe ? 1 rc=1
fib.exe ? 2 rc=1
fib.exe ? 3 rc=2
fib.exe ? 0 rc=0
fib.exe ? 1 rc=1
fib.exe ? 2 rc=1
fib.exe ? 1 rc=1
fib.exe ? 0 rc=0
fib.exe ? 1 rc=1
fib.exe ? 2 rc=1
fib.exe ? 3 rc=2
fib.exe ? 4 rc=3
5

20とか指定すると全然終わらない。

2つのプロセスを同時に起動

WaitForSingleObjectだから1つづつしかプロセス起動しないが、WaitForMultipleObjectsなら2つ起動して両方が終わるのを待つ。

int exec2(int n)
{
    STARTUPINFO         si1 = { 0 };
    PROCESS_INFORMATION pi1 = { 0 };
    char cmd1[1024];
    STARTUPINFO         si2 = { 0 };
    PROCESS_INFORMATION pi2 = { 0 };
    char cmd2[1024];
    sprintf_s(cmd1, "fib.exe ? %d", n-2);
    sprintf_s(cmd2, "fib.exe ? %d", n-1);
    CreateProcess(NULL, cmd1, NULL, NULL, FALSE, 0, NULL, NULL, &si1, &pi1);
    CreateProcess(NULL, cmd2, NULL, NULL, FALSE, 0, NULL, NULL, &si2, &pi2);
    HANDLE hnds[2];
    hnds[0] = pi1.hProcess;
    hnds[1] = pi2.hProcess;
    WaitForMultipleObjects(2, hnds, TRUE, INFINITE);
    DWORD rc1;
    DWORD rc2;
    GetExitCodeProcess(pi1.hProcess, &rc1);
    GetExitCodeProcess(pi2.hProcess, &rc2);
    printf("1: %s rc=%d\n", cmd1, rc1);
    printf("2: %s rc=%d\n", cmd2, rc2);
    n = rc1 + rc2;
    return n;
}

int main(int argc, char **argv)
{
    int n = 0;
    if (argc == 2) {
        n = atoi(argv[1]);
    } else if (argc == 3) {
        n = atoi(argv[2]);
    }
    if (n >= 2) {
        n = exec2(n);
    }
    if (argc == 2) {
        printf("%d\n", n);
    }
    return n;
}

fib.exeってビルドして起動してみる。

> fib.exe 5
1: fib.exe ? 0 rc=0
2: fib.exe ? 1 rc=1
1: fib.exe ? 0 rc=0
2: fib.exe ? 1 rc=1
1: fib.exe ? 1 rc=1
2: fib.exe ? 2 rc=1
1: fib.exe ? 1 rc=1
2: fib.exe ? 2 rc=1
1: fib.exe ? 0 rc=0
2: fib.exe ? 1 rc=1
1: fib.exe ? 2 rc=1
2: fib.exe ? 3 rc=2
1: fib.exe ? 3 rc=2
2: fib.exe ? 4 rc=3
5

なんかシャキーンって表示された。

計測してみる

v1とv2と呼ぶ。
timeitというリソースキット?のツールがあったので、それを使う。

v1: 10を指定

Version Number:   Windows NT 6.2 (Build 9200)
Exit Time:        1:08 pm, Tuesday, February 20 2018
Elapsed Time:     0:00:02.902
Process Time:     0:00:00.000
System Calls:     591034
Context Switches: 65178
Page Faults:      260403
Bytes Read:       92279880
Bytes Written:    62186
Bytes Other:      3994500

v2: 10を指定

Version Number:   Windows NT 6.2 (Build 9200)
Exit Time:        1:09 pm, Tuesday, February 20 2018
Elapsed Time:     0:00:00.776
Process Time:     0:00:00.015
System Calls:     403732
Context Switches: 52465
Page Faults:      256848
Bytes Read:       93085068
Bytes Written:    35650
Bytes Other:      3906064

体感でも分かるが、やはりv2は速い。

v1: 20を指定

いつ終わるか分からん。

V2: 20を指定

osがガタガタで仮想メモリがアウト。fib.exeのプロセス数が5000とか表示していた。

hiuchida
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away