public static void Factorise(int K, int M, int N, float[,] V, float[,] W, float[,] H, int ITERATIONS) { double[] rmses = new double[NUM_THREADS]; float[,] WH = new float[M, N]; // Computational enhancement with sparse matrices MultiMap <int, int> M_sparse; MultiMap <int, int> N_sparse; FindSparseLocations(M, N, V, out M_sparse, out N_sparse); // Random initialisation of W and H Tools.InitialiseRandomMatrices(K, M, N, W, H); // And now we iterate int iteration = 0; while (true) { Logging.Info("Iteration {0}", iteration); // Calculate the new WH every now and then to check our progress... ++iteration; if (0 == iteration % 3) { int num_threads_running = 0; for (int thread_id = 0; thread_id < NUM_THREADS; ++thread_id) { int thread_id_local = thread_id; ThreadTools.StartThread(o => PARALLEL_WH(K, M, N, V, W, H, WH, NUM_THREADS, thread_id_local, ref num_threads_running, rmses)); } Tools.WaitForThreads(ref num_threads_running); // Tally the RMSE double rmse = 0; for (int thread_id = 0; thread_id < NUM_THREADS; ++thread_id) { rmse += rmses[thread_id]; } rmse = Math.Sqrt(rmse); Logging.Info("Iteration {0} has an RMSE of {1}", iteration, rmse); // Check exit condition if (iteration >= ITERATIONS) { break; } } // Calculate the new H { int num_threads_running = 0; for (int thread_id = 0; thread_id < NUM_THREADS; ++thread_id) { int thread_id_local = thread_id; ThreadTools.StartThread(o => PARALLEL_H(K, M, N, V, W, H, WH, M_sparse, N_sparse, NUM_THREADS, thread_id_local, ref num_threads_running)); } Tools.WaitForThreads(ref num_threads_running); } // Calculate the new W { int num_threads_running = 0; for (int thread_id = 0; thread_id < NUM_THREADS; ++thread_id) { int thread_id_local = thread_id; ThreadTools.StartThread(o => PARALLEL_W(K, M, N, V, W, H, WH, M_sparse, N_sparse, NUM_THREADS, thread_id_local, ref num_threads_running)); } Tools.WaitForThreads(ref num_threads_running); } } }
public static void Factorise(int K, int M, int N, float[,] V, float[,] W, float[,] H, int ITERATIONS) { double[] rmses = new double[NUM_THREADS]; float[,] WH = new float[M, N]; // Random initialisation of W and H Tools.InitialiseRandomMatrices(K, M, N, W, H); // And now we iterate int iteration = 0; while (true) { Logging.Info("Iteration {0}", iteration); // Calculate the new WH (for efficiency reasons so we dont have to calc twice) { int num_threads_running = 0; for (int thread_id = 0; thread_id < NUM_THREADS; ++thread_id) { int thread_id_local = thread_id; ThreadTools.StartThread(o => PARALLEL_WH(K, M, N, V, W, H, WH, NUM_THREADS, thread_id_local, ref num_threads_running, rmses)); } Tools.WaitForThreads(ref num_threads_running); // Tally the RMSE double rmse = 0; for (int thread_id = 0; thread_id < NUM_THREADS; ++thread_id) { rmse += rmses[thread_id]; } rmse = Math.Sqrt(rmse); Logging.Info("Iteration {0} has an RMSE of {1}", iteration, rmse); } // Check exit condition ++iteration; if (iteration >= ITERATIONS) { break; } // Calculate the new P { int num_threads_running = 0; for (int thread_id = 0; thread_id < NUM_THREADS; ++thread_id) { int thread_id_local = thread_id; ThreadTools.StartThread(o => PARALLEL_H(K, M, N, V, W, H, WH, NUM_THREADS, thread_id_local, ref num_threads_running)); } Tools.WaitForThreads(ref num_threads_running); } // Calculate the new A { int num_threads_running = 0; for (int thread_id = 0; thread_id < NUM_THREADS; ++thread_id) { int thread_id_local = thread_id; ThreadTools.StartThread(o => PARALLEL_W(K, M, N, V, W, H, WH, NUM_THREADS, thread_id_local, ref num_threads_running)); } Tools.WaitForThreads(ref num_threads_running); } } }