我的老师要求我通过c#中的线程将两个n×n矩阵相乘。
如何并行执行for
?
代码的时间复杂度如何?
此代码是否并行运行?
for(int k = 0; k < n; k++)
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
{
K_copy = k;
i_copy = i;
j_copy = j;
myThread[k, i, j] = new Thread(() => computeMultiply(k_copy, i_copy, j_copy));
myThread[k, i, j].Start();
}
要相乘2个矩阵(matA和matB),我们需要3个for
序列方法,如下所示:
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
for(int k=0;k<n;k++)
matC[i,j]=matC[i,j]+matA[i,k]*matB[k,j];
考虑到我们有n ^ 3个处理器,因此我们可以并行进行乘法。因此,每个乘法都在O(1)中执行...因此我们可以降低时间复杂度。但是我没有n ^ 3个处理器,所以我必须使用线程来模拟这种情况。另一方面,我的老师想模拟SIMD系统中的运行并模拟Parallel.For的线程!
我在A,B等处理器中都有寄存器,但是我像每个线程的寄存器一样使用matP。
这是computeMultiply函数:
static void computeMultiply(int k, int i, int j)
{
matP[k, i, j] = matA[i, k] * matB[k, j];
}
答案 0 :(得分:0)
您可以这样做:
Parallel.For(0, n, i=>
{
for(int j = 0; j < n; j++)
for(int k = 0; k < n; k++)
{
myThread[i, j] += matA[i,k]*matB[k,j];
}
});
如果您的老师想笑一点,这是Parallel.For的一些 veerery 基本实现。
public sealed class MyThreadPool : IDisposable
{
private readonly Thread[] _threads;
private readonly ConcurrentQueue<Action> _tasks = new ConcurrentQueue<Action>();
private bool _enabled;
private MyThreadPool(int count)
{
_enabled = true;
_threads = new Thread[count];
for (var i = 0; i < count; i++)
{
_threads[i] = new Thread(Consume);
_threads[i].Start();
}
}
public static void For(int threadCount, int from, int to, Action<int> action)
{
using (var pool = new MyThreadPool(threadCount))
{
for (int i = from; i < to; i++)
{
var captured = i;
pool.EnqueueTask(() => action(captured));
}
pool.WaitTillCompletion();
}
}
private void Consume()
{
while (_enabled)
{
Action task;
if (_tasks.TryDequeue(out task))
{
try
{
task();
}
catch
{
//can log error here if you want
}
}
else
{
Thread.Sleep(0);
}
}
}
public void EnqueueTask(Action action)
{
_tasks.Enqueue(action);
}
public void WaitTillCompletion()
{
while (!_tasks.IsEmpty)
Thread.Sleep(0);
}
public void Dispose()
{
_enabled = false;
foreach (var t in _threads)
{
t.Join();
}
}
}
像这样使用它:
var threadCount = Environment.ProcessorCount * 4; //this is as much as modern processor can squese out of itself, larger values used only for IO loads, not for computation.
MyThreadPool.For(threadCount, n, i=>
{
for(int j = 0; j < n; j++)
for(int k = 0; k < n; k++)
{
myThread[i, j] += matA[i,k]*matB[k,j];
}
});