- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在从事一个在 .Net 中开发的遗传机器学习项目(相对于 Matlab – My Norm)。我不是专业的 .net 编码员,所以请原谅任何笨拙的实现。
该项目本身非常庞大,因此我不会向您介绍全部细节,但基本上,大量人工神经网络(如决策树)都在一个问题域上进行评估,在本例中,该问题域使用了一系列感官输入。种群中表现最好的被允许繁殖和产生后代(继承 parent 双方的倾向),而表现不佳的则被杀死或从种群中繁殖出来。进化一直持续到找到可接受的解决方案。一旦找到,最终进化的“网络”就会从实验室中提取出来,并放置在一个轻量级的现实世界应用程序中。该技术可用于开发非常复杂的控制解决方案,通常编程几乎不可能或太耗时,例如自动汽车驾驶、机械稳定性控制、数据中心负载平衡等。
无论如何,该项目到目前为止取得了巨大的成功,并产生了惊人的结果,但唯一的问题是一旦我转向更大的数据集,性能就会非常慢。我希望只是我的代码,所以非常感谢专家的帮助。
在这个项目中,收敛到接近理想的解决方案通常需要大约 7 天的处理时间!只是对参数进行一点调整并等待结果太痛苦了。
基本上,多个并行线程需要读取一个非常大的数据集的顺序部分(数据一旦加载就不会改变)。该数据集由大约 300 到 1000 个连续的 Double 和超过 500k 行的任何内容组成。由于数据集可以超过 2GB 的 .Net 对象限制,它不能存储在普通的二维数组中——最简单的方法是使用单个数组的通用列表。
并行可扩展性似乎是一个很大的限制因素,因为在具有 32 个 Xeon 核心的服务器上运行代码通常吃大数据集作为早餐不会比 Corei3 桌面产生太多性能提升!
随着内核数量的增加,性能提升会迅速减少。
通过分析代码(以我有限的知识),我得到的印象是从多个线程读取数据集存在大量争用。
我曾尝试使用 Jagged 数组和各种并发集合来试验不同的数据集实现,但无济于事。
我已经为基准测试编写了一些快速而肮脏的代码,它类似于原始的核心实现,但仍然表现出类似的读取性能问题和并行可伸缩性问题。
任何想法或建议将不胜感激或确认这是我将要得到的最好的。
非常感谢
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; }
}
}
}
}
最佳答案
首先,回答任何性能问题的唯一方法是分析应用程序。我正在使用 VS 2012 内置分析器 - 还有其他的 https://stackoverflow.com/a/100490/19624
从最初通读代码开始,即静态分析,唯一让我印象深刻的是循环内 Temp 的持续重新分配;这效率不高,如果可能的话需要移出循环。
使用分析器,您可以看到发生了什么:
我首先使用您发布的代码进行了概要分析(如果您没有发布完整的可编译问题示例,我将获得最高分)。
这告诉我,大部分在循环内部,我将分配移动到 Parallel.ForEach 循环。
Parallel.ForEach(_NeuralNetworkPopulation, _Network =>
{
double[] Temp = new double[Features + 1];
EvaluateNetwork(_Network, Temp);
});
所以我从上面可以看出,在重新分配上有 4.4% 的浪费;但可能不足为奇的是,内循环占据了 87.6%。
这让我想到了我的第一条优化规则,即首先检查您的算法而不是优化代码。好的算法的糟糕实现通常比高度优化的糟糕算法更快。
去掉Temp的重复分配,图片略有变化;
还值得通过指定并行度进行一些调整;我发现 Parallel.ForEach 足以满足我的使用需求,但同样,通过手动将工作划分为队列可能会获得更好的结果。
Parallel.ForEach(_NeuralNetworkPopulation,
new ParallelOptions { MaxDegreeOfParallelism = 32 },
_Network =>
{
double[] Temp = new double[Features + 1];
EvaluateNetwork(_Network, Temp);
});
在运行时,我得到了我所期望的 CPU 使用率:尽管我的机器还在运行另一个耗时的进程,该进程处于基本级别(下表中的峰值是在分析此程序时)。
总结一下
关于c# - 从多个并行线程读取大型数据集的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17838456/
有没有办法同时运行 2 个不同的代码块。我一直在研究 R 中的并行包,它们似乎都基于在循环中运行相同的函数。我正在寻找一种同时运行不同函数的方法(循环的 1 次迭代)。例如,我想在某个数据对象上创建一
无论如何增加 Parallel.For 启动后的循环次数?示例如下: var start = 0; var end = 5; Parallel.For(start, end, i => { C
我是 Golang 的新手,正在尝试了解并发和并行。我阅读了下面提到的关于并发和并行的文章。我执行了相同的程序。但没有得到相同的(混合字母和字符)输出。首先获取所有字母,然后获取字符。似乎并发不工作,
我正在寻找同时迭代 R 中两个或多个字符向量/列表的方法,例如。有没有办法做这样的事情: foo <- c('a','c','d') bar <- c('aa','cc','dd') for(i in
我对 Raku 很陌生,我对函数式方法有疑问,尤其是 reduce。 我最初有这样的方法: sub standardab{ my $mittel = mittel(@_); my $foo =
我最近花了很多时间来学习实时音频处理的细节,我发现的大多数库/工具都是c / c++代码或脚本/图形语言的形式,并在其中编译了c / c++代码。引擎盖。 使用基于回调的API,与GUI或App中的其
我正在使用 JMeter 进行图像负载测试。我有一个图像名称数组并遍历该数组,我通过 HTTP 请求获取所有图像。 -> loop_over_image - for loop controller
我整个晚上都在困惑这个问题...... makeflags = ['--prefix=/usr','--libdir=/usr/lib'] rootdir='/tmp/project' ps = se
我正在尝试提高计算图像平均值的方法的性能。 为此,我使用了两个 For 语句来迭代所有图像,因此我尝试使用一个 Parallel For 来改进它,但结果并不相同。 我做错了吗?或者是什么导致了差异?
假设您有一个并行 for 循环实现,例如ConcRT parallel_for,将所有工作放在一个 for 循环体内总是最好的吗? 举个例子: for(size_t i = 0; i < size()
我想并行运行一部分代码。目前我正在使用 Parallel.For 如何让10、20或40个线程同时运行 我当前的代码是: Parallel.For(1, total, (ii) =>
我使用 PAY API 进行了 PayPal 自适应并行支付,其中无论用户(买家)购买什么,都假设用户购买了总计 100 美元的商品。在我的自适应并行支付中,有 2 个接收方:Receiver1 和
我正在考虑让玩家加入游戏的高效算法。由于会有大量玩家,因此算法应该是异步的(即可扩展到集群中任意数量的机器)。有细节:想象有一个无向图(每个节点都是一个玩家)。玩家之间的每条边意味着玩家可以参加同一场
我有一个全局变量 volatile i = 0; 和两个线程。每个都执行以下操作: i++; System.out.print(i); 我收到以下组合。 12、21 和 22。 我理解为什么我没有得到
我有以下称为 pgain 的方法,它调用我试图并行化的方法 dist: /***************************************************************
我有一个 ruby 脚本读取一个巨大的表(约 2000 万行),进行一些处理并将其提供给 Solr 用于索引目的。这一直是我们流程中的一大瓶颈。我打算在这里加快速度,我想实现某种并行性。我对 Ru
我正在研究 Golang 并遇到一个问题,我已经研究了几天,我似乎无法理解 go routines 的概念以及它们的使用方式。 基本上我是在尝试生成数百万条随机记录。我有生成随机数据的函数,并将创建一
我希望 for 循环使用 go 例程并行。我尝试使用 channel ,但没有用。我的主要问题是,我想在继续之前等待所有迭代完成。这就是为什么在它不起作用之前简单地编写 go 的原因。我尝试使用 ch
我正在使用 import Control.Concurrent.ParallelIO.Global main = parallel_ (map processI [1..(sdNumber runPa
我正在尝试通过 makePSOCKcluster 连接到另一台计算机: library(parallel) cl ... doTryCatch -> recvData -> makeSOCKm
我是一名优秀的程序员,十分优秀!