我目前正在尝试使用特定数量的线程将两个矩阵相乘。
我最近发布了一篇与同一任务(old approach)相关的帖子,但现在我已经改变了解决此任务的策略。
我不再使用线程池了。相反,我自己管理线程。
这是我目前的解决方案:
class Matrix
{
// Stores a random generator
Random rnd = new Random();
int[,] map = new int[16, 16];
// Stores the cell which have to be processed
static List<Cell> TaskList = new List<Cell>();
// Stores the threads used for processing
static List<Thread> Threads = new List<Thread>();
// Stores the result matrix
static Matrix c = new Matrix();
// Fill a matrix with an given value
public void fillMatrixWithValue(int val)
{
for (int i = 0; i < map.GetLength(0); i++)
{
for (int j = 0; j < map.GetLength(1); j++)
{
map[i, j] = val;
}
}
}
// Fill a matrix with random values
public void fillMatrixWithRandomValues(int range = 10)
{
for (int i = 0; i < map.GetLength(0); i++)
{
for (int j = 0; j < map.GetLength(1); j++)
{
map[i, j] = getRandomNumber(range);
}
}
}
// Return a random number for random matrix generation
int getRandomNumber(int range)
{
return rnd.Next(1, range);
}
// Print a matrix to console
public void printMatrix()
{
for (int i = 0; i < map.GetLength(0); i++)
{
for (int j = 0; j < map.GetLength(1); j++)
{
Console.Write(map[i, j] + " ");
}
Console.WriteLine();
}
Console.WriteLine();
}
// Calculate the result matrix sequential
public static Matrix MultiplyMatricesSequential(Matrix a, Matrix b)
{
Matrix c = new Matrix();
for (int row = 0; row < a.map.GetLength(0); row++)
{
for (int col = 0; col < a.map.GetLength(1); col++)
{
for (int i = 0; i < a.map.GetLength(0); i++)
{
c.map[row, col] += a.map[row, i] * b.map[i, col];
}
}
}
return c;
}
// Calculate the result matrix parallel via threads
public static Matrix MultiplyMatricesAsynchronous(Matrix a, Matrix b, int amountOfThreads)
{
// Stores the row values needed for calculation of the result cell value
int[] row = new int[a.map.GetLength(0)];
// Stores the col values needed for calculation of the result cell value
int[] col = new int[a.map.GetLength(1)];
// Store the position indizes of the result cell
int x = 0, y = 0;
// Calculate and store the cell information used for calculation of the result value
for (int i = 0; i < a.map.GetLength(0); i++)
{
for (int j = 0; j < a.map.GetLength(1); j++)
{
for (int k = 0; k < a.map.GetLength(0); k++)
{
row[k] = a.map[i, k];
col[k] = b.map[k, j];
x = i;
y = j;
}
TaskList.Add(new Cell(row, col, x, y));
}
}
// Get the intial amount of threads (created by OS)
int amountOfInitialThreads = Process.GetCurrentProcess().Threads.Count;
// Run till all cells have been processed
do
{
// Only create a new thread if thread limit (user input) has not been reached yet
if (Process.GetCurrentProcess().Threads.Count < (amountOfInitialThreads + amountOfThreads))
{
Thread temp = new Thread(new ThreadStart(calculateCell));
Threads.Add(temp);
temp.Start();
}
foreach (Thread t in Threads)
{
t.Join();
}
} while (TaskList.Count > 0);
return c;
}
// Calculate and set the result value in the result matrix
static void calculateCell()
{
Cell cell = null;
if (TaskList.Count != 0)
{
// Lock the list so that threads do not take the same cell for processing
lock (TaskList)
{
cell = TaskList[TaskList.Count - 1];
TaskList.RemoveAt(TaskList.Count - 1);
}
int temp = 0;
// Calculate and set the result cell value
for (int i = 0; i < cell.row.Length; i++)
{
temp = i;
c.map[cell.x, cell.y] += cell.row[temp] * cell.col[temp];
}
}
}
}
}
我已经实现了一个单元类,它存储结果矩阵值的位置以及计算结果值所需的基本矩阵的行和列值。
现在的问题是结果矩阵的每个单元格都填充了相同的值。
我不明白的是每个线程获得正确的x和y值,但是错误的行和col值(每个线程采用相同的行和col值)。在我看来,某些值在线程之间以某种方式共享,而有些则不是。
我已经做了很多调试,但我无法弄清楚我做错了什么。
你们中有人能够这样做吗?
答案 0 :(得分:1)
问题出在这里
// Stores the row values needed for calculation of the result cell value
int[] row = new int[a.map.GetLength(0)];
// Stores the col values needed for calculation of the result cell value
int[] col = new int[a.map.GetLength(1)];
// Store the position indizes of the result cell
int x = 0, y = 0;
// Calculate and store the cell information used for calculation of the result value
for (int i = 0; i < a.map.GetLength(0); i++)
{
for (int j = 0; j < a.map.GetLength(1); j++)
{
for (int k = 0; k < a.map.GetLength(0); k++)
{
row[k] = a.map[i, k];
col[k] = b.map[k, j];
请注意,对于所有单元格使用相同的row / col数组,因为它们是在循环外部定义的。
您需要在“j”循环内移动数组声明,以便为每个单元格获取一组新的数组