我正在開發.Net中的遺傳機器學習項目(而不是Matlab - 我的標準)。我不是親.net編碼器,所以請原諒任何noobish實現。性能閱讀大型數據集從多個並行線程
該項目本身是巨大的,所以我不會給你帶來完整的細節,但基本上人口的神經網絡(如決策樹)是在一個問題領域進行評估,在這種情況下,使用感官輸入流。人口中表現最佳的人員可以繁殖和生產後代(繼承父母的傾向),而窮人表演者則被淘汰或繁殖出人羣。進化一直持續到找到可接受的解決方案。一旦找到,最終進化的'網絡'將從實驗室中提取出來,放置在一個輕量級的真實世界的應用程序中。該技術可用於開發非常複雜的控制解決方案,這對於正常編程來說幾乎是不可能或太耗時的,例如自動駕駛汽車,機械穩定性控制,數據中心負載平衡等等。
無論如何,該項目已迄今爲止取得了巨大的成功,並且產生了驚人的結果,但唯一的問題是,一旦我轉向更大的數據集,性能會非常低下。我希望只是我的代碼,所以真的很感謝一些專家的幫助。
在這個項目中,收斂接近理想的解決方案往往需要7天左右的處理!只是對參數進行一些調整並等待結果太痛苦了。
基本上,多個並行線程需要閱讀一個非常大的數據集的順序區段(數據沒有改變一次加載)。該數據集由大約300至1000個雙打組成,超過500k行。由於數據集可能超過2GB的.Net對象限制,因此無法將其存儲在普通的2d數組中 - 最簡單的方法是使用單個數組的通用列表。
並行可伸縮性似乎是一個很大的限制因素,因爲在32位Xeon內核的服務器上運行代碼,通常在早餐時使用大數據集並不會比Corei3桌面帶來更多的性能提升!
隨着內核數量的增加,性能增益會迅速減小。
從剖析代碼(我有限的知識),我得到的印象是有爭論的從多個線程讀取數據集,數額巨大。
我試着使用交錯數組不同的數據集的實現和各種併發集合,但無濟於事試驗。
我已經懷孕了的基準測試代碼快速和髒位類似於核心實現原始的,仍然表現出類似的讀取性能問題和並行可擴展性問題。
任何想法或建議,將不勝感激或確認,這是我要得到最好的。
非常感謝
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
//Benchmark script to time how long it takes to read dataset per iteration
namespace Benchmark_Simple
{
class Program
{
public static TrainingDataSet _DataSet;
public static int Features = 100; //Real test will require 300+
public static int Rows = 200000; //Real test will require 500K+
public static int _PopulationSize = 500; //Real test will require 1000+
public static int _Iterations = 10;
public static List<NeuralNetwork> _NeuralNetworkPopulation = new List<NeuralNetwork>();
static void Main()
{
Stopwatch _Stopwatch = new Stopwatch();
//Create Dataset
Console.WriteLine("Creating Training DataSet");
_DataSet = new TrainingDataSet(Features, Rows);
Console.WriteLine("Finished Creating Training DataSet");
//Create Neural Network Population
for (int i = 0; i <= _PopulationSize - 1; i++)
{
_NeuralNetworkPopulation.Add(new NeuralNetwork());
}
//Main Loop
for (int i = 0; i <= _Iterations - 1; i++)
{
_Stopwatch.Restart();
Parallel.ForEach(_NeuralNetworkPopulation, _Network => { EvaluateNetwork(_Network); });
//######## Removed for simplicity ##########
//Run Evolutionary Genetic Algorithm on population - I.E. Breed the strong, kill of the weak
//##########################################
//Repeat until acceptable solution is found
Console.WriteLine("Iteration time: {0}", _Stopwatch.ElapsedMilliseconds/1000);
_Stopwatch.Stop();
}
Console.ReadLine();
}
private static void EvaluateNetwork(NeuralNetwork Network)
{
//Evaluate network on 10% of the Training Data at a random starting point
double Score = 0;
Random Rand = new Random();
int Count = (Rows/100) * 10;
int RandonStart = Rand.Next(0, Rows - Count);
//The data must be read sequentially
for (int i = RandonStart; i <= RandonStart + Count; i++)
{
double[] NetworkInputArray = _DataSet.GetDataRow(i);
//####### Dummy Evaluation - just give it somthing to do for the sake of it
double[] Temp = new double[NetworkInputArray.Length + 1];
for (int j = 0; j <= NetworkInputArray.Length - 1; j++)
{
Temp[j] = Math.Log(NetworkInputArray[j] * Rand.NextDouble());
}
Score += Rand.NextDouble();
//##################
}
Network.Score = Score;
}
public class TrainingDataSet
{
//Simple demo class of fake data for benchmarking
private List<double[]> DataList = new List<double[]>();
public TrainingDataSet(int Features, int Rows)
{
Random Rand = new Random();
for (int i = 1; i <= Rows; i++)
{
double[] NewRow = new double[Features];
for (int j = 0; j <= Features - 1; j++)
{
NewRow[j] = Rand.NextDouble();
}
DataList.Add(NewRow);
}
}
public double[] GetDataRow(int Index)
{
return DataList[Index];
}
}
public class NeuralNetwork
{
//Simple Class to represent a dummy Neural Network -
private double _Score;
public NeuralNetwork()
{
}
public double Score
{
get { return _Score; }
set { _Score = value; }
}
}
}
}
有一兩件事我注意到的是你正在使用Parallel.ForEach這將阻止。你看看ThreadPool.QueueWorkItem和PLINQ嗎?我的經驗 – Learner
Parallel.Foreach在整個列表中有很高的爭用。通過將totalItems除以procs的數量,我可以獲得更好的性能: 'var groupCount = totalItems/numProcessors; (0,groupCount,(groupId)=> {var start = groupId * groupsize; var end = Math.Min(start + groupsize,totalItems); for(int i = start; i
Handcraftsman