【发布时间】:2016-09-28 14:19:25
【问题描述】:
我正在尝试将线程支持添加到在多个维度中散列坐标的方法中。这里的长期目标是包含 FNV1A 哈希,但只要在 Hash 方法中简单地初始化坐标数组,就会出现减速。
我迭代了一百万次,对于 1 个线程,我得到的秒表时间约为 300 毫秒。对于 8 个线程,时间会达到约 6000 毫秒。
这是一个虚假的分享问题吗?如果是这样,我担心哈希会随着填充和偏移量注入数组而恶化。任何有关使用本地数组执行此操作的帮助将不胜感激。非常感谢!
public class Foo : MonoBehaviour {
#region Fields
private readonly int iterations = 1000000;
private readonly int threadNum = 1;
private int iterationsCompleted = 0;
#endregion
void Start () {
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
Multithread();
stopWatch.Stop();
UnityEngine.Debug.Log(stopWatch.Elapsed.TotalMilliseconds);
}
private void Multithread() {
for (int i = 0; i < threadNum; i++) {
Hash hash = new Hash();
new Thread(() => {
while (Interlocked.Increment(ref iterationsCompleted) < iterations) {
hash.Get(0, 0, 0);
}
UnityEngine.Debug.Log("Finished thread");
}).Start();
}
while (iterationsCompleted < iterations);
}
}
public class Hash {
#region Fields
// FNV parameters can be found at http://www.isthe.com/chongo/tech/comp/fnv/#FNV-param
private const uint _FNVPrime = 16777619;
private const uint _FNVOffset = 2166136261;
private const uint _FNVMask8 = (1<<8)-1;
#endregion
#region Class Methods
private static uint FNV1A(uint[] data) {
uint hash = _FNVOffset;
int dataSize = data.Length * sizeof(UInt32);
byte[] byteArray = new byte[dataSize];
Buffer.BlockCopy(data, 0, byteArray, 0, dataSize);
for (int i = 0; i < dataSize; i++) {
hash = hash ^ byteArray[i];
hash = hash * _FNVPrime;
}
return hash;
}
public uint Get(int x, int y, uint seed) {
uint[] data = new uint[3] { (uint)x, (uint)y, seed };
//return FNV1A(data);
return 0;
}
#endregion
}
【问题讨论】:
-
我不确定这一点,因为我还没有统一使用线程,但我认为 MonoBehaviour 派生类会出现多线程问题(至少是从它继承的函数)。
-
一定是分配新数组的开销。您有两个选择:使用 FNV1A 和固定数量的整数而不是数组,或者预分配一个数组,每个线程一个。
-
@TamasHegedus 请注意,对于一百万次迭代和 1 个线程,我的秒表时间接近约 300 毫秒。碰撞到 8 将时间推到 ~6000 毫秒。这似乎不像数组开销。我也会将该信息添加到帖子中。
-
@RichardHorne 我想我找到了问题所在。更新您的完整代码,以便我进行测试。
-
threadNum,iterationsCompleted和iterations的值是多少?
标签: c# arrays multithreading unity3d hash