我尝试将线程支持添加到散列多维坐标的方法中。这里的长期目标是包含LineHeightSpan
哈希值,但只要在FNV1A
方法中初始化坐标数组就会出现减速。
我迭代了一百万次,对于一个线程,我得到了约300毫秒的秒表时间。对于8个线程,时间碰到~6000ms。
这是一个错误的分享问题吗?如果是这样,我担心的是散列会因填充和偏移注入阵列而恶化。任何有关使用本地阵列执行此操作的帮助将不胜感激。非常感谢!
Hash
答案 0 :(得分:1)
内存分配似乎是这里的问题。我创建了两个数组static
,然后在函数外部分配了一次内存。每次访问它时,locked
都是数组,以确保另一个Thread
没有访问它们。即使在使用lock
关键字后,也不确定我的代码有多安全。
无相关问题:
在主while (iterationsCompleted < iterations);
上调用 Thread
。这并不好,每次调用Multithread()
并且仍在运行时,它都会暂时冻结Unity。我在其上添加了另一个Thread
,它将启动whenMultithread()
。因此,现在正在从这个新的Thread
而不是主Thread
调用其他线程。
在我的电脑上测试结果
原始代码:
1 thread = 454.3515
8 threads = 655.008
修改后的代码:
1 thread = 296.794
8 threads = 107.8898
8
个帖子的效果提升超过6x
。
所有测试都是在代码中包含return FNV1A(data);
并且代码中已删除/注释return 0;
的情况下完成的。
现在,您的工作是确保您获得的数据/哈希符合您的预期。
public class Foo : MonoBehaviour
{
#region Fields
private readonly int iterations = 1000000;
private readonly int threadNum = 1;
private int iterationsCompleted = 0;
#endregion
void Start()
{
Multithread();
}
private void Multithread()
{
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
//Start new Thread so that while (iterationsCompleted < iterations) ; will not run in the main loop
new Thread(() =>
{
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) ;
stopWatch.Stop();
UnityEngine.Debug.Log(stopWatch.Elapsed.TotalMilliseconds);
}).Start();
}
}
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;
private const int FIXEDSIZE = 3;
private readonly System.Object locker = new System.Object();
#endregion
#region Class Methods
private static uint FNV1A(uint[] data)
{
uint hash = _FNVOffset;
Buffer.BlockCopy(data, 0, byteArray, 0, byteArray.Length);
for (int i = 0; i < byteArray.Length; i++)
{
hash = hash ^ byteArray[i];
hash = hash * _FNVPrime;
}
return hash;
}
static byte[] byteArray = new byte[FIXEDSIZE * sizeof(UInt32)];
static uint[] data = new uint[3] { (uint)0, (uint)0, 0 };
public uint Get(int x, int y, uint seed)
{
lock (locker)
{
data[0] = (uint)x;
data[1] = (uint)y;
data[2] = (uint)seed;
return FNV1A(data);
}
}
#endregion
}