问题描述
我做了光线跟踪的业余爱好项目,最初我是用结构为我的矢量和雷对象,我想到了一个光线跟踪是完美的情况下使用他们:你们创造数百万他们,他们不会活得更长久不是一个单一的方法,他们是轻量级的。然而,通过简单地改变'结构'对向量和雷'类',我有一个非常显著的性能增益。
I'm doing a raytracer hobby project, and originally I was using structs for my Vector and Ray objects, and I thought a raytracer was the perfect situation to use them: you create millions of them, they don't live longer than a single method, they're lightweight. However, by simply changing 'struct' to 'class' on Vector and Ray, I got a very significant performance gain.
怎么办?他们都是小(3花车向量,向量2为雷),不要过度复制左右。我需要做的,当然,当它们传递到方法,但这是不可避免的。那么,什么是使用结构时杀死表现常见的陷阱?我读过的MSDN文章,上面写着以下内容:
What gives? They're both small (3 floats for Vector, 2 Vectors for a Ray), don't get copied around excessively. I do pass them to methods when needed of course, but that's inevitable. So what are the common pitfalls that kill performance when using structs? I've read this MSDN article that says the following:
当你运行这个例子,你会看到,结构循环是快几个数量级。然而,当你像对待对象提防使用值类型是很重要的。这增加了额外的装箱和拆箱的开销到您的程序,并可以最终花费你更多比它,如果你已经坚持了对象!要看到这个动作,修改上面的代码中使用的foo和酒吧的数组。你会发现,业绩或多或少平等的。
这可是相当老(2001)和整个他们将在数组会导致装箱/拆箱给我的印象奇怪。真的吗?然而,我预先计算初级光线并把它们放在一个数组,所以我接受了这篇文章,并计算出的主光线,当我需要它,不会将它们添加到一个数组,但它并没有改变什么:与类,它仍然快1.5倍。
It's however quite old (2001) and the whole "putting them in an array causes boxing/unboxing" struck me as odd. Is that true? However, I did pre-calculate the primary rays and put them in an array, so I took up on this article and calculated the primary ray when I needed it and never added them to an array, but it didn't change anything: with classes, it was still 1.5x faster.
我运行.NET 3.5 SP1,我相信固定的一个问题,即结构的方法没有曾经在成荫,以至于不能被它的。
I am running .NET 3.5 SP1 which I believe fixed an issue where struct methods weren't ever in-lined, so that can't be it either.
所以基本上:任何提示,要考虑的事情和如何避免
So basically: any tips, things to consider and what to avoid?
编辑:正如一些答案建议,我已经成立了一个测试项目中,我已经试过路过结构作为参考。
As suggested in some answers, I've set up a test project where I've tried passing structs as ref. The methods for adding two Vectors:
public static VectorStruct Add(VectorStruct v1, VectorStruct v2)
{
return new VectorStruct(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z);
}
public static VectorStruct Add(ref VectorStruct v1, ref VectorStruct v2)
{
return new VectorStruct(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z);
}
public static void Add(ref VectorStruct v1, ref VectorStruct v2, out VectorStruct v3)
{
v3 = new VectorStruct(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z);
}
对于每一个我得到了以下的基准方法的变化:
For each I got a variation of the following benchmark method:
VectorStruct StructTest()
{
Stopwatch sw = new Stopwatch();
sw.Start();
var v2 = new VectorStruct(0, 0, 0);
for (int i = 0; i < 100000000; i++)
{
var v0 = new VectorStruct(i, i, i);
var v1 = new VectorStruct(i, i, i);
v2 = VectorStruct.Add(ref v0, ref v1);
}
sw.Stop();
Console.WriteLine(sw.Elapsed.ToString());
return v2; // To make sure v2 doesn't get optimized away because it's unused.
}
似乎都执行几乎相同。难道他们得到JIT以什么都是通过这个结构的最佳方式优化?
All seem to perform pretty much identical. Is it possible that they get optimized by the JIT to whatever is the optimal way to pass this struct?
EDIT2:我必须在我的测试项目使用结构是这样的说明的比使用一个类快约50%。为什么这是对我的光线跟踪不同的我不知道。
I must note by the way that using structs in my test project is about 50% faster than using a class. Why this is different for my raytracer I don't know.
推荐答案
基本上,不要让他们太大了,当你可以围绕由参传递它们。我发现这完全相同的方式......通过改变我的矢量和Ray类结构。
Basically, don't make them too big, and pass them around by ref when you can. I discovered this the exact same way... By changing my Vector and Ray classes to structs.
通过正在传递更多的内存,它势必会造成高速缓存抖动。
With more memory being passed around, it's bound to cause cache thrashing.
这篇关于如果是结构的答案吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!