C++ で、スクリプト言語と同様に機能するアプリケーションを作成したいと考えています。
「セットアップ時間」中の入力から、各変数が配置される大きなグローバル配列と、関数のシーケンスを別の配列に定義します ( "LogicElement") を呼び出します (使用する変数などのパラメーターを含みます)。
1 つの実装は次のようになります。
class LogicElement_Generic
{
public:
virtual void calc() const = 0;
};
class LogicElement_Mul : public LogicElement_Generic
{
int &to;
const int &from1;
const int &from2;
public:
LogicElement_Mul( int &_to, const int &_from1, const int &_from2 ) : to(_to), from1(_from1), from2(_from2)
{}
void calc() const
{
to = from1 * from2;
}
};
char globalVariableBuffer[1000]; // a simple binary buffer
LogicElement_Generic *le[10];
int main( void )
{
// just a demo, this would be setup from e.g. an input file:
int *to = (int*)globalVariableBuffer;
int *from1 = (int*)(globalVariableBuffer + sizeof(int));
int *from2 = (int*)(globalVariableBuffer + 2*sizeof(int));
*from1 = 2;
*from2 = 3;
le[0] = new LogicElement_Mul( *to, *from1, *from2 );
// doing all calculations:
// finally it would be a loop iterating over all calculation functions,
// over and over again - the area in the code where all the resources
// would be burned...
le[0]->calc();
return *to;
}
意図したとおりに機能しますが、作成されたアセンブリを見てください。
78 .section .text._ZNK16LogicElement_Mul4calcEv,"axG",@progbits,_ZNK16LogicElement_Mul4calcEv,comdat
79 .align 2
80 .weak _ZNK16LogicElement_Mul4calcEv
82 _ZNK16LogicElement_Mul4calcEv:
83 .LFB6:
17:.../src/test.cpp **** void calc() const
84 .loc 1 17 0
85 .cfi_startproc
86 0000 55 pushq %rbp
87 .LCFI6:
88 .cfi_def_cfa_offset 16
89 .cfi_offset 6, -16
90 0001 4889E5 movq %rsp, %rbp
91 .LCFI7:
92 .cfi_def_cfa_register 6
93 0004 48897DF8 movq %rdi, -8(%rbp)
18:.../src/test.cpp **** {
19:.../src/test.cpp **** to = from1 * from2;
94 .loc 1 19 0
95 0008 488B45F8 movq -8(%rbp), %rax
96 000c 488B4008 movq 8(%rax), %rax
97 0010 488B55F8 movq -8(%rbp), %rdx
98 0014 488B5210 movq 16(%rdx), %rdx
99 0018 8B0A movl (%rdx), %ecx
100 001a 488B55F8 movq -8(%rbp), %rdx
101 001e 488B5218 movq 24(%rdx), %rdx
102 0022 8B12 movl (%rdx), %edx
103 0024 0FAFD1 imull %ecx, %edx
104 0027 8910 movl %edx, (%rax)
20:.../src/test.cpp **** }
105 .loc 1 20 0
106 0029 5D popq %rbp
107 .LCFI8:
108 .cfi_def_cfa 7, 8
109 002a C3 ret
110 .cfi_endproc
アセンブリ ライン 95 .. 104 を見ると、変数ごとに 3 つの間接指定が使用されていることがわかります。
コードのこの部分 (calc() メソッド) は最終的に非常に高速に呼び出されるため、(一般的な C/C++ によって) 可能な限り最小の CPU サイクルとメモリ帯域幅を使用したいと考えています。
また、必要なロックを制限するためにマルチスレッド アプローチでダブル バッファリングを実行できるように、レイアウトがまったく同じ 2 つの可変バッファを用意する (上記のコードには示されていません) ことも実現したいと考えています (正確な実装の詳細は、この質問)。
したがって、大きな質問は次のとおりです。
- アーキテクチャを変更して、calc() でのメモリ間接の量を減らすにはどうすればよいですか?
(変数配列のオフセット アドレスを取得するためのものと、変数自体を取得するためのものの 2 つだけを期待していましたが、上記のコードをオフセットを使用するように変更した私の実験では、事態はさらに悪化しました!) - クラスと LogicElements の配列をセットアップして、計算メソッドの呼び出しが最小限のリソースしか使用しないようにするためのより良い方法はありますか?