我用perf创建了带注释的跟踪。由于某些原因,百分比最高的指令的类型为ldp:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int i, n;
vector<char> input;
char chp;
cout << "Enter a expression" << endl;
while (1)
{
cin.get(chp);
if (chp == '\n') break;
input.push_back(chp);
}
n = input.size();
char* tab = new char[n] {};
for (i = 0; i < n; i++)
{
tab[i] = input[i];
}
int l = strlen(tab);
for (int i = 0; i < l; i++)
{
cout << "tab[" << i << "] is " << tab[i] << endl;
}
cin.get();
}
这是一个错误吗?还是因为ldp sped取决于缓存而提示L1 / L2缓存不好?
编辑:
这里是perf注释输出的摘录。摘录来自我的函数使用的glm矩阵乘法:
5.56 │ ldp s9, s8, [x28,#80]
37.65 │ ldp s2, s3, [x19,#24]
37.65 │ ldp s2, s3, [x19,#24]
致谢
编辑:我添加了该方法当前版本的源代码,该方法在10000个输入元素上产生约2500个缓存未命中。也许有人还有想法:
│ _ZN3glmmlIdLNS_9precisionE0EEENS_7tmat4x4IT_XT0_EE8row_typeERKNS4_8col_typeERKS4_(): ▒
│ ) ▒
│ { ▒ ▒
│ ▒
│ return typename tmat4x4<T, P>::row_type( ◆
│ m[0][0] * v[0] + m[0][1] * v[1] + m[0][2] * v[2] + m[0][3] * v[3], ▒
28.86 │ 40: ldp d3, d0, [x0] ▒
│ add x4, x4, #0x20 ▒
│ ldp d18, d10, [x1] ▒
│ m[1][0] * v[0] + m[1][1] * v[1] + m[1][2] * v[2] + m[1][3] * v[3], ▒
0.34 │ ldp d21, d24, [x1,#32] ▒
│ m[2][0] * v[0] + m[2][1] * v[1] + m[2][2] * v[2] + m[2][3] * v[3], ▒
0.34 │ ldp d20, d23, [x1,#64] ▒
│ m[3][0] * v[0] + m[3][1] * v[1] + m[3][2] * v[2] + m[3][3] * v[3]); ▒
0.34 │ ldp d19, d22, [x1,#96] ▒
│ m[1][0] * v[0] + m[1][1] * v[1] + m[1][2] * v[2] + m[1][3] * v[3], ▒
│ fmul d24, d0, d24 ▒
│ m[0][0] * v[0] + m[0][1] * v[1] + m[0][2] * v[2] + m[0][3] * v[3], ▒
10.07 │ ldp d2, d1, [x0,#16] ▒
│ m[2][0] * v[0] + m[2][1] * v[1] + m[2][2] * v[2] + m[2][3] * v[3], ▒
│ fmul d23, d0, d23 ▒
│ m[3][0] * v[0] + m[3][1] * v[1] + m[3][2] * v[2] + m[3][3] * v[3]); ▒
0.34 │ ldp d8, d6, [x1,#16] ▒
│ fmul d22, d0, d22 ▒
0.34 │ ldp d17, d7, [x1,#48] ▒
│ m[0][0] * v[0] + m[0][1] * v[1] + m[0][2] * v[2] + m[0][3] * v[3], ▒
│ fmul d0, d0, d10 ▒
│ m[3][0] * v[0] + m[3][1] * v[1] + m[3][2] * v[2] + m[3][3] * v[3]); ▒
│ ldp d16, d5, [x1,#80] ▒
│ m[1][0] * v[0] + m[1][1] * v[1] + m[1][2] * v[2] + m[1][3] * v[3], ▒
│ fmadd d21, d3, d21, d24 ▒
│ m[3][0] * v[0] + m[3][1] * v[1] + m[3][2] * v[2] + m[3][3] * v[3]); ▒
0.34 │ ldp d9, d4, [x1,#112] ▒
│ m[2][0] * v[0] + m[2][1] * v[1] + m[2][2] * v[2] + m[2][3] * v[3], ▒
│ fmadd d20, d3, d20, d23 ▒
│ m[3][0] * v[0] + m[3][1] * v[1] + m[3][2] * v[2] + m[3][3] * v[3]); ▒
│ fmadd d19, d3, d19, d22 ▒
│ m[0][0] * v[0] + m[0][1] * v[1] + m[0][2] * v[2] + m[0][3] * v[3], ▒
│ fmadd d0, d18, d3, d0 ▒
│ m[1][0] * v[0] + m[1][1] * v[1] + m[1][2] * v[2] + m[1][3] * v[3], ▒
0.67 │ fmadd d17, d2, d17, d21 ▒
│ m[2][0] * v[0] + m[2][1] * v[1] + m[2][2] * v[2] + m[2][3] * v[3], ▒
│ fmadd d16, d2, d16, d20 ▒
│ m[3][0] * v[0] + m[3][1] * v[1] + m[3][2] * v[2] + m[3][3] * v[3]); ▒
│ fmadd d7, d1, d7, d17 ▒
│ fmadd d5, d1, d5, d16 ▒
1.01 │ fmadd d9, d2, d9, d19 ▒
│ m[0][0] * v[0] + m[0][1] * v[1] + m[0][2] * v[2] + m[0][3] * v[3], ▒
│ fmadd d2, d8, d2, d0 ▒
│ m[3][0] * v[0] + m[3][1] * v[1] + m[3][2] * v[2] + m[3][3] * v[3]); ▒
│ fmadd d4, d1, d4, d9 ▒
│ fmadd d1, d6, d1, d2 ▒
0.67 │ add x0, x0, #0x20
ASM:
inline void
transformVector ( glm::mat4 const & matrix,
std::vector < glm::vec4 > const & input,
std::vector < glm::vec4 > & output )
{
float32x4x4_t iMatrix = *(float32x4x4_t *)&matrix;
float32x4_t rslt;
std::vector < glm::vec4 >::const_iterator inVertexStart = input.begin();
std::vector < glm::vec4 >::const_iterator inVertexEnd = input.end();
std::vector < glm::vec4 >::iterator outVertexStart = output.begin();
for ( ; inVertexStart != inVertexEnd; inVertexStart++, outVertexStart++ )
{
const float32x4_t input_local = *( float32x4_t const * )&(*inVertexStart);
rslt = vmulq_f32( iMatrix.val[0], input_local);
rslt = vmlaq_f32(rslt, iMatrix.val[1], input_local);
rslt = vmlaq_f32(rslt, iMatrix.val[2], input_local);
rslt = vmlaq_f32(rslt, iMatrix.val[3], input_local);
vst1q_f32( (float32_t*)&( *outVertexStart ), rslt);
}
}