SWIG包装器使用指南——(五)(完)C#使用SWIG时性能优化
·
一、前言
跨平台、跨语言调用本身就是一个很耗费性能的操作,P/Invoke也不例外。但C++/CLI相对P/Invoke来说性能较好。
所以对于P/Invoke来说,我们的优化目标就是尽可能的减少P/Invoke的调用,C++与C#两个层之间要高内聚低耦合,能用函数间调用完成的,就觉不要通过P/Invoke。
以下优化实践将会不断更新。
二、优化实践
2.1 提高std::vector的遍历性能
假如我们定义了如下的c++数据结构:
class TriangleInfo
{
public:
TriangleInfo() = default;
TriangleInfo(Vector3 p1, Vector3 p2, Vector3 p3)
: Pos1(p1), Pos2(p2), Pos3(p3)
{
}
TriangleInfo(Vector3 p1, Vector3 p2, Vector3 p3,Vector3 normal)
: Pos1(p1), Pos2(p2), Pos3(p3), Normal(normal)
{
}
public:
Vector3 Normal{ 0,0,0 };
Vector3 Pos1{ 0,0,0 };
Vector3 Pos2 { 0,0,0 };
Vector3 Pos3 { 0,0,0 };
};
struct Vector3
{
public:
Vector3() = default;
Vector3(float x, float y, float z)
: X(x), Y(y), Z(z)
{
}
static Vector3 Lerp(const Vector3& a, const Vector3& b, float t)
{
t = std::clamp(t, 0.0f, 1.0f); // 限制在 [0,1]
return Vector3(
a.X + (b.X - a.X) * t,
a.Y + (b.Y - a.Y) * t,
a.Z + (b.Z - a.Z) * t
);
}
public:
float X;
float Y;
float Z;
};
同时声明了swig接口文件:
%template(Vector3Vector) std::vector<Vector3>;
%template(TriangleInfoVector) std::vector<TriangleInfo>;
当你在c#侧直接遍历TriangleInfoVector对象时,每遍历一次就会产生一次P/Invoke调用,当数据量很大时,总时间将巨慢无比。
所以我们要想下如何一次性能把收据接收完以减少遍历次数?vector本身提供的data()函数就可以为我们所用,它返回了数组的首地址。
在swig接口文件中增加如下扩展代码:
%define VECTOR_EXTEND(T)
%extend std::vector<T> {
void* getData()
{
return $self->data();
}
}
%enddef
VECTOR_EXTEND(TriangleInfo);
VECTOR_EXTEND(Vector3);
VECTOR_EXTEND(float);
在c#侧如下调用即可:
TriangleInfoVector triangles; //you get form somewhere
int triCount = triangles.Count;
TrianglePO[] arr = new TrianglePO[triCount];
unsafe
{
fixed (TrianglePO* dst = arr)
{
Buffer.MemoryCopy((void*)triangles.getData(), dst, triCount * sizeof(TrianglePO), triCount * sizeof(TrianglePO));
}
}
注意,为了性能c#这里定义了两个与c++结构一样的类型,而没有直接复用c++那边生成的数据结构。
[StructLayout(LayoutKind.Sequential)]
public struct Vector3PO
{
public float X;
public float Y;
public float Z;
}
[StructLayout(LayoutKind.Sequential)]
public struct TrianglePO
{
public Vector3PO Normal;
public Vector3PO Pos1;
public Vector3PO Pos2;
public Vector3PO Pos3;
}
[StructLayout(LayoutKind.Sequential)]:按照声明顺序布局内存结构,与c++那边的定义对应起来。
更多推荐


所有评论(0)