2016-04-23 87 views
0

我目前正在尝试使用特定数量的线程乘以两个矩阵。矩阵乘法使用用户设置线程数

我最近发布了一篇关于同一个任务的帖子(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

你为什么要设置这个“行[K] = a.map [I,K]。”在我内,j循环?您正在设置相同的行(和列)阵列n次。看起来问题在那里 – tede24

回答

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]; 

注意您正在使用的,因为它们是环外的定义的所有细胞中的同一行/列阵列。

您需要将里面的“J”循环数组声明得到一套新阵列的每一个细胞