速度ではなくサイズを最適化すると、GCCが15〜20%高速なコードを生成するのはなぜですか?

451
Ali 2013-10-20 10:36.

私は2009年に、GCC(少なくとも私のプロジェクトと私のマシン)は、速度(または)ではなくサイズ-Os)を最適化すると、著しく高速なコードを生成する傾向があることに最初に気づきました。それ以来、なぜだろうと思っていました。-O2-O3

私は、この驚くべき動作を示し、ここに投稿するのに十分小さい(かなりばかげた)コードを作成することができました。

const int LOOP_BOUND = 200000000;

__attribute__((noinline))
static int add(const int& x, const int& y) {
    return x + y;
}

__attribute__((noinline))
static int work(int xval, int yval) {
    int sum(0);
    for (int i=0; i<LOOP_BOUND; ++i) {
        int x(xval+sum);
        int y(yval+sum);
        int z = add(x, y);
        sum += z;
    }
    return sum;
}

int main(int , char* argv[]) {
    int result = work(*argv[1], *argv[2]);
    return result;
}

でコンパイルした場合-Os、このプログラムの実行には0.38秒かかり、-O2またはでコンパイルした場合は0.44秒かかります-O3。これらの時間は一貫して、実質的にノイズなしで取得されます(gcc 4.7.2、x86_64 GNU / Linux、Intel Corei5-3320M)。

(更新:すべてのアセンブリコードをGitHubに移動しました:fno-align-*フラグが同じ効果を持つため、投稿が肥大化し、質問にほとんど価値がないようです。)

ここでアセンブリが生成される-Os-O2

残念ながら、アセンブリについての私の理解は非常に限られているため、次に行ったことが正しいかどうかはわかりません。-O2アセンブリを-Os 取得し.p2align行を除いてすべての違いをアセンブリにマージしまし。結果はここにあります。このコードはまだ0.38秒で実行され、唯一の違いは .p2align ものです。

私が正しく推測すると、これらはスタック整列のためのパディングです。よるとなぜのNOPとGCCパッド機能していますか?コードがより速く実行されることを期待して行われますが、私の場合、この最適化は明らかに裏目に出ました。

この場合の原因はパディングですか?なぜ、どのように?

それが作るノイズは、タイミングのマイクロ最適化をほとんど不可能にします。

CまたはC ++ソースコードでマイクロ最適化(スタックアラインメントとは関係ありません)を実行するときに、このような偶発的なラッキー/アンラッキーアラインメントが干渉しないようにするにはどうすればよいですか?


更新:

Pascal Cuoqの答えに続いて、私はアライメントを少しいじりました。-O2 -fno-align-functions -fno-align-loopsgccに渡すことにより、すべて.p2alignがアセンブリから削除され、生成された実行可能ファイルは0.38秒で実行されます。gccのドキュメントによると:

-Osはすべての-O2最適化を有効にします[ただし] -Osは次の最適化フラグを無効にします。

  -falign-functions  -falign-jumps  -falign-loops
  -falign-labels  -freorder-blocks  -freorder-blocks-and-partition
  -fprefetch-loop-arrays

ですから、それは(ミス)アライメントの問題のように思えます。

Marat Dukhanの回答で-march=native示唆されているように、私はまだ懐疑的です。私は、それがこの(ミス)アライメントの問題を妨害しているだけではないと確信していません。それは私のマシンにはまったく影響しません。(それにもかかわらず、私は彼の答えに賛成した。)


更新2:

-Os写真から取り出すことができます。以下の時間は、

  • -O2 -fno-omit-frame-pointer 0.37秒

  • -O2 -fno-align-functions -fno-align-loops 0.37秒

  • -S -O2次にadd()work()0.37秒後にアセンブリを手動で移動します

  • -O2 0.44秒

私にはadd()、通話サイトからの距離が非常に重要であるように見えます。私が試してみましたperfが、の出力perf statとは、perf report私には非常にほとんど意味がありません。しかし、私はそれから1つの一貫した結果しか得ることができませんでした:

-O2

 602,312,864 stalled-cycles-frontend   #    0.00% frontend cycles idle
       3,318 cache-misses
 0.432703993 seconds time elapsed
 [...]
 81.23%  a.out  a.out              [.] work(int, int)
 18.50%  a.out  a.out              [.] add(int const&, int const&) [clone .isra.0]
 [...]
       ¦   __attribute__((noinline))
       ¦   static int add(const int& x, const int& y) {
       ¦       return x + y;
100.00 ¦     lea    (%rdi,%rsi,1),%eax
       ¦   }
       ¦   ? retq
[...]
       ¦            int z = add(x, y);
  1.93 ¦    ? callq  add(int const&, int const&) [clone .isra.0]
       ¦            sum += z;
 79.79 ¦      add    %eax,%ebx

の場合fno-align-*

 604,072,552 stalled-cycles-frontend   #    0.00% frontend cycles idle
       9,508 cache-misses
 0.375681928 seconds time elapsed
 [...]
 82.58%  a.out  a.out              [.] work(int, int)
 16.83%  a.out  a.out              [.] add(int const&, int const&) [clone .isra.0]
 [...]
       ¦   __attribute__((noinline))
       ¦   static int add(const int& x, const int& y) {
       ¦       return x + y;
 51.59 ¦     lea    (%rdi,%rsi,1),%eax
       ¦   }
[...]
       ¦    __attribute__((noinline))
       ¦    static int work(int xval, int yval) {
       ¦        int sum(0);
       ¦        for (int i=0; i<LOOP_BOUND; ++i) {
       ¦            int x(xval+sum);
  8.20 ¦      lea    0x0(%r13,%rbx,1),%edi
       ¦            int y(yval+sum);
       ¦            int z = add(x, y);
 35.34 ¦    ? callq  add(int const&, int const&) [clone .isra.0]
       ¦            sum += z;
 39.48 ¦      add    %eax,%ebx
       ¦    }

の場合-fno-omit-frame-pointer

 404,625,639 stalled-cycles-frontend   #    0.00% frontend cycles idle
      10,514 cache-misses
 0.375445137 seconds time elapsed
 [...]
 75.35%  a.out  a.out              [.] add(int const&, int const&) [clone .isra.0]                                                                                     ¦
 24.46%  a.out  a.out              [.] work(int, int)
 [...]
       ¦   __attribute__((noinline))
       ¦   static int add(const int& x, const int& y) {
 18.67 ¦     push   %rbp
       ¦       return x + y;
 18.49 ¦     lea    (%rdi,%rsi,1),%eax
       ¦   const int LOOP_BOUND = 200000000;
       ¦
       ¦   __attribute__((noinline))
       ¦   static int add(const int& x, const int& y) {
       ¦     mov    %rsp,%rbp
       ¦       return x + y;
       ¦   }
 12.71 ¦     pop    %rbp
       ¦   ? retq
 [...]
       ¦            int z = add(x, y);
       ¦    ? callq  add(int const&, int const&) [clone .isra.0]
       ¦            sum += z;
 29.83 ¦      add    %eax,%ebx

add()遅いケースでは、への呼び出しが停止しているようです。

私は自分のマシンで吐き出すことができるすべてのものを調べましperf -e。上記の統計だけではありません。

同じ実行可能ファイルの場合、stalled-cycles-frontendは実行時間と線形相関を示します。それほど明確に相関するものは他にありませんでした。(stalled-cycles-frontend異なる実行可能ファイルを比較することは私には意味がありません。)

最初のコメントとして出てきたキャッシュミスを含めました。上記のキャッシュミスperfだけでなく、自分のマシンで測定できるすべてのキャッシュミスを調べました。キャッシュミスは非常にノイズが多く、実行時間との相関関係はほとんどまたはまったくありません。

6 answers

521
Marat Dukhan 2013-10-20 12:24.

デフォルトでは、コンパイラは「平均的な」プロセッサ用に最適化します。異なるプロセッサは異なる命令シーケンスを優先するため、によって有効化されたコンパイラの最適化は-O2平均的なプロセッサに利益をもたらす可能性がありますが、特定のプロセッサのパフォーマンスは低下します(同じことが当てはまります-Os)。異なるプロセッサで同じ例を試してみると、一部のプロセッサではメリットがあり-O2、他のプロセッサでは-Os最適化に有利であることがわかります。

time ./test 0 0いくつかのプロセッサでの結果は次のとおりです(ユーザー時間の報告)。

Processor (System-on-Chip)             Compiler   Time (-O2)  Time (-Os)  Fastest
AMD Opteron 8350                       gcc-4.8.1    0.704s      0.896s      -O2
AMD FX-6300                            gcc-4.8.1    0.392s      0.340s      -Os
AMD E2-1800                            gcc-4.7.2    0.740s      0.832s      -O2
Intel Xeon E5405                       gcc-4.8.1    0.603s      0.804s      -O2
Intel Xeon E5-2603                     gcc-4.4.7    1.121s      1.122s       -
Intel Core i3-3217U                    gcc-4.6.4    0.709s      0.709s       -
Intel Core i3-3217U                    gcc-4.7.3    0.708s      0.822s      -O2
Intel Core i3-3217U                    gcc-4.8.1    0.708s      0.944s      -O2
Intel Core i7-4770K                    gcc-4.8.1    0.296s      0.288s      -Os
Intel Atom 330                         gcc-4.8.1    2.003s      2.007s      -O2
ARM 1176JZF-S (Broadcom BCM2835)       gcc-4.6.3    3.470s      3.480s      -O2
ARM Cortex-A8 (TI OMAP DM3730)         gcc-4.6.3    2.727s      2.727s       -
ARM Cortex-A9 (TI OMAP 4460)           gcc-4.6.3    1.648s      1.648s       -
ARM Cortex-A9 (Samsung Exynos 4412)    gcc-4.6.3    1.250s      1.250s       -
ARM Cortex-A15 (Samsung Exynos 5250)   gcc-4.7.2    0.700s      0.700s       -
Qualcomm Snapdragon APQ8060A           gcc-4.8       1.53s       1.52s      -Os

場合によってgccは、特定のプロセッサ用に最適化するように依頼することで、不利な最適化の影響を軽減できます(オプション-mtune=nativeまたはを使用-march=native)。

Processor            Compiler   Time (-O2 -mtune=native) Time (-Os -mtune=native)
AMD FX-6300          gcc-4.8.1         0.340s                   0.340s
AMD E2-1800          gcc-4.7.2         0.740s                   0.832s
Intel Xeon E5405     gcc-4.8.1         0.603s                   0.803s
Intel Core i7-4770K  gcc-4.8.1         0.296s                   0.288s

更新:アイビーブリッジベースのコアには、3つのバージョンi3をgcc4.6.44.7.3および4.8.1有意に異なる性能を有する)を生成バイナリをするが、アセンブリコードは、微妙な変化を有しています。これまでのところ、私はこの事実の説明がありません。

からのアセンブリgcc-4.6.4 -Os(0.709秒で実行):

00000000004004d2 <_ZL3addRKiS0_.isra.0>:
  4004d2:       8d 04 37                lea    eax,[rdi+rsi*1]
  4004d5:       c3                      ret

00000000004004d6 <_ZL4workii>:
  4004d6:       41 55                   push   r13
  4004d8:       41 89 fd                mov    r13d,edi
  4004db:       41 54                   push   r12
  4004dd:       41 89 f4                mov    r12d,esi
  4004e0:       55                      push   rbp
  4004e1:       bd 00 c2 eb 0b          mov    ebp,0xbebc200
  4004e6:       53                      push   rbx
  4004e7:       31 db                   xor    ebx,ebx
  4004e9:       41 8d 34 1c             lea    esi,[r12+rbx*1]
  4004ed:       41 8d 7c 1d 00          lea    edi,[r13+rbx*1+0x0]
  4004f2:       e8 db ff ff ff          call   4004d2 <_ZL3addRKiS0_.isra.0>
  4004f7:       01 c3                   add    ebx,eax
  4004f9:       ff cd                   dec    ebp
  4004fb:       75 ec                   jne    4004e9 <_ZL4workii+0x13>
  4004fd:       89 d8                   mov    eax,ebx
  4004ff:       5b                      pop    rbx
  400500:       5d                      pop    rbp
  400501:       41 5c                   pop    r12
  400503:       41 5d                   pop    r13
  400505:       c3                      ret

からのアセンブリgcc-4.7.3 -Os(0.822秒で実行):

00000000004004fa <_ZL3addRKiS0_.isra.0>:
  4004fa:       8d 04 37                lea    eax,[rdi+rsi*1]
  4004fd:       c3                      ret

00000000004004fe <_ZL4workii>:
  4004fe:       41 55                   push   r13
  400500:       41 89 f5                mov    r13d,esi
  400503:       41 54                   push   r12
  400505:       41 89 fc                mov    r12d,edi
  400508:       55                      push   rbp
  400509:       bd 00 c2 eb 0b          mov    ebp,0xbebc200
  40050e:       53                      push   rbx
  40050f:       31 db                   xor    ebx,ebx
  400511:       41 8d 74 1d 00          lea    esi,[r13+rbx*1+0x0]
  400516:       41 8d 3c 1c             lea    edi,[r12+rbx*1]
  40051a:       e8 db ff ff ff          call   4004fa <_ZL3addRKiS0_.isra.0>
  40051f:       01 c3                   add    ebx,eax
  400521:       ff cd                   dec    ebp
  400523:       75 ec                   jne    400511 <_ZL4workii+0x13>
  400525:       89 d8                   mov    eax,ebx
  400527:       5b                      pop    rbx
  400528:       5d                      pop    rbp
  400529:       41 5c                   pop    r12
  40052b:       41 5d                   pop    r13
  40052d:       c3                      ret

からのアセンブリgcc-4.8.1 -Os(0.994秒で実行):

00000000004004fd <_ZL3addRKiS0_.isra.0>:
  4004fd:       8d 04 37                lea    eax,[rdi+rsi*1]
  400500:       c3                      ret

0000000000400501 <_ZL4workii>:
  400501:       41 55                   push   r13
  400503:       41 89 f5                mov    r13d,esi
  400506:       41 54                   push   r12
  400508:       41 89 fc                mov    r12d,edi
  40050b:       55                      push   rbp
  40050c:       bd 00 c2 eb 0b          mov    ebp,0xbebc200
  400511:       53                      push   rbx
  400512:       31 db                   xor    ebx,ebx
  400514:       41 8d 74 1d 00          lea    esi,[r13+rbx*1+0x0]
  400519:       41 8d 3c 1c             lea    edi,[r12+rbx*1]
  40051d:       e8 db ff ff ff          call   4004fd <_ZL3addRKiS0_.isra.0>
  400522:       01 c3                   add    ebx,eax
  400524:       ff cd                   dec    ebp
  400526:       75 ec                   jne    400514 <_ZL4workii+0x13>
  400528:       89 d8                   mov    eax,ebx
  40052a:       5b                      pop    rbx
  40052b:       5d                      pop    rbp
  40052c:       41 5c                   pop    r12
  40052e:       41 5d                   pop    r13
  400530:       c3                      ret
191
Ali 2013-10-25 05:32.

私の同僚は、私の質問に対するもっともらしい答えを見つけるのを手伝ってくれました。彼は256バイト境界の重要性に気づきました。彼はここに登録されておらず、私に自分で答えを投稿するように勧めました(そしてすべての名声を得る)。


短い答え:

この場合の原因はパディングですか?なぜ、どのように?

それはすべて、調整に要約されます。配置はパフォーマンスに大きな影響を与える可能性があるため-falign-*、そもそもフラグがあります。

(偽の?)バグレポートをgcc開発者に提出しまし。デフォルトの動作は、「ループをデフォルトで8バイトに整列しますが、10バイトを超える入力が必要ない場合は、16バイトに整列しようとします」であることがわかります。どうやら、このデフォルトは、この特定のケースと私のマシンでは最良の選択ではありません。Clang 3.4(トランク)-O3は適切な配置を行い、生成されたコードはこの奇妙な動作を示しません。

もちろん、不適切な調整が行われると、事態はさらに悪化します。不要な/不適切な配置は、理由もなくバイトを消費し、キャッシュミスなどを増やす可能性があります。

それが作るノイズは、タイミングのマイクロ最適化をほとんど不可能にします。

CまたはC ++ソースコードでマイクロ最適化(スタックアラインメントとは関係ありません)を実行するときに、このような偶発的なラッキー/アンラッキーアラインメントが干渉しないようにするにはどうすればよいですか?

gccに正しい位置合わせを行うように指示するだけです。

g++ -O2 -falign-functions=16 -falign-loops=16


長い答え:

次の場合、コードの実行速度が低下します。

  • XXバイト境界カットadd()途中で(XXマシン依存します)。

  • の呼び出しがバイト境界add()を飛び越える必要がXXあり、ターゲットが整列されていない場合。

  • add()位置合わせされていない場合 。

  • ループが整列していない場合。

最初の2つは、MaratDukhanが親切に投稿したコードと結果に美しく表示されます。この場合、gcc-4.8.1 -Os(0.994秒で実行されます):

00000000004004fd <_ZL3addRKiS0_.isra.0>:
  4004fd:       8d 04 37                lea    eax,[rdi+rsi*1]
  400500:       c3   

256バイトの境界add()が真ん中でカットされadd()、ループも整列されません。驚き、驚き、これは最も遅いケースです!

場合gcc-4.7.3 -Os(0.822秒で実行される)、コールド部に256バイト境界のみ切り込み(どちらもループもadd()あるカット)。

00000000004004fa <_ZL3addRKiS0_.isra.0>:
  4004fa:       8d 04 37                lea    eax,[rdi+rsi*1]
  4004fd:       c3                      ret

[...]

  40051a:       e8 db ff ff ff          call   4004fa <_ZL3addRKiS0_.isra.0>

何も調整されておらず、への呼び出しadd()は256バイトの境界を飛び越える必要があります。このコードは2番目に遅いです。

場合はgcc-4.6.4 -Os何も揃っていないが(0.709秒で実行)、への呼び出しはadd()256バイト境界を飛び越えるする必要はありませんし、ターゲットが正確に32バイト先です。

  4004f2:       e8 db ff ff ff          call   4004d2 <_ZL3addRKiS0_.isra.0>
  4004f7:       01 c3                   add    ebx,eax
  4004f9:       ff cd                   dec    ebp
  4004fb:       75 ec                   jne    4004e9 <_ZL4workii+0x13>

これは3つすべての中で最速です。なぜ256バイトの境界が彼のマシンで特別なのか、私はそれを理解するのは彼に任せます。私はそのようなプロセッサを持っていません。

さて、私のマシンでは、この256バイトの境界効果は得られません。私のマシンでは、機能とループの調整のみが開始されます。合格するとg++ -O2 -falign-functions=16 -falign-loops=16、すべてが正常に戻ります。常に最速のケースが発生し、時間は-fno-omit-frame-pointerフラグの影響を受けなくなります。私g++ -O2 -falign-functions=32 -falign-loops=32は16の倍数を渡すことができますが、コードもそれに敏感ではありません。

私は2009年に、速度(-O2または-O3)ではなくサイズ(-Os)を最適化すると、gcc(少なくとも私のプロジェクトとマシン)が著しく高速なコードを生成する傾向があることに最初に気づきました。それ以来、なぜか。

おそらく、この例のように、配置に敏感なホットスポットがあったということです。フラグをいじることによって(の-Os代わりに渡す-O2)、それらのホットスポットは偶然に幸運な方法で整列され、コードはより速くなりました。サイズの最適化とは何の関係もありませんでした。これらは、ホットスポットがより適切に配置されたというまったくの偶然によるものでした。これからは、アラインメントがプロジェクトに与える影響を確認します。

ああ、そしてもう1つ。例に示されているようなホットスポットはどのように発生しますか?このような小さな関数のインライン化はどのようにadd()失敗するのでしょうか。

このことを考慮:

// add.cpp
int add(const int& x, const int& y) {
    return x + y;
}

および別のファイル:

// main.cpp
int add(const int& x, const int& y);

const int LOOP_BOUND = 200000000;

__attribute__((noinline))
static int work(int xval, int yval) {
    int sum(0);
    for (int i=0; i<LOOP_BOUND; ++i) {
        int x(xval+sum);
        int y(yval+sum);
        int z = add(x, y);
        sum += z;
    }
    return sum;
}

int main(int , char* argv[]) {
    int result = work(*argv[1], *argv[2]);
    return result;
}

そして次のようにコンパイルされます:g++ -O2 add.cpp main.cpp

      gccはインライン化されませんadd()

それだけです。OPのようなホットスポットを意図せずに作成するのは簡単です。もちろん、それは部分的に私のせいです。gccは優れたコンパイラです。上記を次のようにコンパイルするとg++ -O2 -flto add.cpp main.cpp、つまり、リンク時間の最適化を実行すると、コードは0.19秒で実行されます。

(OPではインライン化が人為的に無効になっているため、OPのコードは2倍遅くなりました)。

74
Gene 2013-10-28 11:07.

私はこの事後承認を追加して、プログラムの全体的なパフォーマンス(大きなプログラムを含む)に対するアライメントの影響が研究されていることを指摘します。たとえば、この記事(およびこのバージョンはCACMにも表示されていると思います)は、リンクの順序とOS環境のサイズの変更だけでパフォーマンスを大幅にシフトするのに十分であったことを示しています。彼らはこれを「ホットループ」の整列に起因すると考えています。

「明らかに悪いことを何もせずに間違ったデータを生成する」というタイトルのこの論文。プログラム実行環境のほとんど制御できない違いによる不注意な実験的バイアスは、おそらく多くのベンチマーク結果を無意味にするだろうと言います。

同じ観察で別の角度に遭遇していると思います。

パフォーマンスが重要なコードの場合、これは、インストール時または実行時に環境を評価し、さまざまに最適化されたバージョンのキールーチンの中からローカルベストを選択するシステムにとってはかなり良い議論です。

34
Pascal Cuoq 2013-10-20 11:13.

私はあなたがしたのと同じ結果を得ることができると思います:

-O2のアセンブリを取得し、.p2align行を除くすべての違いを-Oのアセンブリにマージしました。

…を使用して-O2 -falign-functions=1 -falign-jumps=1 -falign-loops=1 -falign-labels=1。私は-O215年間、これらのオプションを使用してすべてをコンパイルしてきました。これは、測定するたびに単純なものよりも高速でした。

また、まったく異なるコンテキスト(異なるコンパイラを含む)の場合、状況が似いることに気付きました。「速度ではなくコードサイズを最適化する」ことになっているオプションは、コードサイズと速度を最適化します。

私が正しく推測すると、これらはスタック整列のためのパディングです。

いいえ、これはスタックとは何の関係もありません。デフォルトで生成されるNOPと、オプション-falign- * = 1が防止するのはコードアラインメント用です。

なぜGCCパッドはNOPで機能するのですか?これは、コードがより高速に実行されることを期待して行われますが、私の場合、この最適化は明らかに裏目に出ました。

この場合の原因はパディングですか?なぜ、どのように?

パディングが原因である可能性が非常に高いです。パディングが必要であり、場合によっては有用であると思われる理由は、コードが通常16バイトの行でフェッチされるためです(詳細については、プロセッサのモデルによって異なるAgner Fogの最適化リソースを参照してください)。関数、ループ、またはラベルを16バイトの境界に揃えると、関数またはループを含めるために必要な行が1行少なくなる可能性が統計的に増加します。明らかに、これらのNOPはコード密度を低下させ、したがってキャッシュ効率を低下させるため、逆効果になります。ループとラベルの場合、NOPを1回実行する必要がある場合もあります(ジャンプからではなく、実行がループ/ラベルに正常に到着したとき)。

11
Joshua 2013-10-25 05:48.

プログラムがCODEL1キャッシュによって制限されている場合、サイズの最適化が突然支払いを開始します。

私が最後にチェックしたとき、コンパイラはすべての場合にこれを理解するのに十分賢いわけではありません。

あなたの場合、-O3はおそらく2つのキャッシュラインに十分なコードを生成しますが、-Osは1つのキャッシュラインに収まります。

7
Daniel Frey 2013-10-23 09:11.

私は決してこの分野の専門家ではありませんが、分岐予測に関しては、最新のプロセッサは非常に敏感であることを覚えているようです。分岐を予測するために使用されるアルゴリズムは、ターゲットの距離や方向など、コードのいくつかのプロパティに基づいています(または少なくともアセンブラーコードを書いた時代に戻っていました)。

頭に浮かぶシナリオは小さなループです。ブランチが逆方向に進み、距離がそれほど遠くない場合、すべての小さなループがこのように行われるため、ブランチの予測はこの場合に最適化されていました。生成されたコードの場所addと場所を入れ替えるworkとき、または両方の位置がわずかに変わるときに、同じルールが機能する可能性があります。

とはいえ、それを確認する方法がわからないので、これが調査したいものかもしれないことをお知らせしたいと思います。

Related questions

MORE COOL STUFF

「水曜日」シーズン1の中心には大きなミステリーがあります

「水曜日」シーズン1の中心には大きなミステリーがあります

Netflixの「水曜日」は、典型的な10代のドラマ以上のものであり、実際、シーズン1にはその中心に大きなミステリーがあります.

ボディーランゲージの専門家は、州訪問中にカミラ・パーカー・ボウルズが輝くことを可能にした微妙なケイト・ミドルトンの動きを指摘しています

ボディーランゲージの専門家は、州訪問中にカミラ・パーカー・ボウルズが輝くことを可能にした微妙なケイト・ミドルトンの動きを指摘しています

ケイト・ミドルトンは、州の夕食会と州の訪問中にカミラ・パーカー・ボウルズからスポットライトを奪いたくなかった、と専門家は言う.

一部のファンがハリー・スタイルズとオリビア・ワイルドの「非常に友好的な」休憩が永続的であることを望んでいる理由

一部のファンがハリー・スタイルズとオリビア・ワイルドの「非常に友好的な」休憩が永続的であることを望んでいる理由

一部のファンが、オリビア・ワイルドが彼女とハリー・スタイルズとの間の「難しい」が「非常に友好的」な分割を恒久的にすることを望んでいる理由を見つけてください.

エリザベス女王の死後、ケイト・ミドルトンはまだ「非常に困難な時期」を過ごしている、と王室の専門家が明らかにする 

エリザベス女王の死後、ケイト・ミドルトンはまだ「非常に困難な時期」を過ごしている、と王室の専門家が明らかにする&nbsp;

エリザベス女王の死後、ケイト・ミドルトンが舞台裏で「非常に困難な時期」を過ごしていたと伝えられている理由を調べてください.

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セント ヘレナ島のジェイコブズ ラダーは 699 段の真っ直ぐ上る階段で、頂上に到達すると証明書が発行されるほどの難易度です。

The Secrets of Airline Travel Quiz

The Secrets of Airline Travel Quiz

Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

バイオニック読書はあなたをより速く読むことができますか?

バイオニック読書はあなたをより速く読むことができますか?

BionicReadingアプリの人気が爆発的に高まっています。しかし、それは本当にあなたを速読術にすることができますか?

HMSプリンスオブウェールズの橋はスターウォーズからまっすぐです

HMSプリンスオブウェールズの橋はスターウォーズからまっすぐです

BAE Systems Maritimeは昨日、英国海軍の2番目のクイーンエリザベスクラスの空母であるHMSプリンスオブウェールズのブリッジモジュールを展開しました。公海を航海するよりも、アウターリムの惑星を周回してタイファイターを発射する必要があるようです。70,000の排水量のトン運搬船は、2020年に就役し、姉のエリザベス女王と同様に、約40機の航空機を運ぶ予定です。

ルイビルはサヨナラゲームでウェイクフォレストを倒すために家を盗んだ

ルイビルはサヨナラゲームでウェイクフォレストを倒すために家を盗んだ

ルイビルは、通常の大学野球の強みであるピッチング、ディフェンス、スマートベースランニングを通じて、全国ランキングのトップ5と19-2の会議記録への道を歩みました。昨夜、彼らは野球の最もエキサイティングなプレーの1つである盗塁を使用して、ウェイクフォレストのスイープを完了しました。

おいしいツイストのためにコーンブレッドであなたの次のサンドイッチを作りましょう

おいしいツイストのためにコーンブレッドであなたの次のサンドイッチを作りましょう

粗いパン粉とふわふわの食感のコーンブレッドは、唐辛子を吸い上げるのに理想的な乗り物です。しかし、それだけではありません。

別の驚くべきマーベルヒーローがキャプテンアメリカに参加します:シビルウォー!

別の驚くべきマーベルヒーローがキャプテンアメリカに参加します:シビルウォー!

ニール・ブロムカンプが、チャッピーが第10地区をどのように遅らせたのかについて話します。フォースの覚醒の噂は、次の予告編に何を期待するかについてのいじめを提供します。

ケイト・ミドルトンとウィリアム王子は、彼らが子供たちと行っているスパイをテーマにした活動を共有しています

ケイト・ミドルトンとウィリアム王子は、彼らが子供たちと行っているスパイをテーマにした活動を共有しています

ケイト・ミドルトンとウィリアム王子は、子供向けのパズルの本の序文を書き、ジョージ王子、シャーロット王女、ルイ王子と一緒にテキストを読むと述べた.

事故で押しつぶされたスイカは、動物を喜ばせ水分補給するために野生生物保護団体に寄付されました

事故で押しつぶされたスイカは、動物を喜ばせ水分補給するために野生生物保護団体に寄付されました

Yak's Produce は、数十個のつぶれたメロンを野生動物のリハビリ専門家であるレスリー グリーンと彼女のルイジアナ州の救助施設で暮らす 42 匹の動物に寄付しました。

デミ・ロヴァートは、新しいミュージシャンのボーイフレンドと「幸せで健康的な関係」にあります: ソース

デミ・ロヴァートは、新しいミュージシャンのボーイフレンドと「幸せで健康的な関係」にあります: ソース

8 枚目のスタジオ アルバムのリリースに向けて準備を進めているデミ ロヴァートは、「スーパー グレート ガイ」と付き合っている、と情報筋は PEOPLE に確認しています。

Plathville の Kim と Olivia Plath が数年ぶりに言葉を交わすことへようこそ

Plathville の Kim と Olivia Plath が数年ぶりに言葉を交わすことへようこそ

イーサン プラスの誕生日のお祝いは、TLC のウェルカム トゥ プラスビルのシーズン 4 のフィナーレで、戦争中の母親のキム プラスと妻のオリビア プラスを結びつけました。

仕事の生産性を高める 8 つのシンプルなホーム オフィスのセットアップのアイデア

仕事の生産性を高める 8 つのシンプルなホーム オフィスのセットアップのアイデア

ホームオフィスのセットアップ術を極めよう!AppExert の開発者は、家族全員が一緒にいる場合でも、在宅勤務の技術を習得しています。祖父や曽祖父が共同家族で暮らしていた頃の記憶がよみがえりました。

2022 年、私たちのデジタル ライフはどこで終わり、「リアル ライフ」はどこから始まるのでしょうか?

20 年前のタイムトラベラーでさえ、日常生活におけるデジタルおよびインターネットベースのサービスの重要性に驚くことでしょう。MySpace、eBay、Napster などのプラットフォームは、高速化に焦点を合わせた世界がどのようなものになるかを示してくれました。

ニューロマーケティングの秘密科学

ニューロマーケティングの秘密科学

マーケティング担当者が人間の欲望を操作するために使用する、最先端の (気味が悪いと言う人もいます) メソッドを探ります。カートをいっぱいにして 3 桁の領収書を持って店を出る前に、ほんの数点の商品を買いに行ったことはありませんか? あなたは一人じゃない。

地理情報システムの日: GIS 開発者として学ぶべき最高の技術スタック

地理情報システムの日: GIS 開発者として学ぶべき最高の技術スタック

私たちが住んでいる世界を確実に理解するには、データが必要です。ただし、空間参照がない場合、このデータは地理的コンテキストがないと役に立たなくなる可能性があります。

Language