这是之前我写的原始的 VB.NET 版本:
http://www.cnblogs.com/RChen/archive/2010/05/17/1737587.html
转化为 C# 版本后,还进行了一些重构。包括修改成了强类型,以及使用了 Parallel.ForEach,但是发现没有收到预期的效果。性能提升比较少。
研究后发现,其实问题的关键在于要通过某种方式对遍历的可能性进行剪枝,这样才能减少遍历次数,从而提升性能。而且,由于结果是通过 yield return 和 IEnumerable 实现的,并没有实现 IList 或者 Array. 所以它本质上并不支持按索引范围拆分的 Parallel.ForEach 工作方式,而实际估计是使用的几个 chunk 轮番读取的低效方式,这样在各个 chunk 之间就有线程同步的开销,如前文所说。这个性能优化只好留待后面有空再继续研究。
下面是目前的状况的实现代码:
using System.Collections.Generic; |
using System.Threading.Tasks; |
using System.Collections; |
namespace NonDeterministicEngineCS |
static void Main( string [] args) |
Benchmarking( new Action(Test1), "Test1() 执行完成,花费:{0}毫秒。" ); |
Console.WriteLine( "====================================================" ); |
Benchmarking( new Action(Test2), "Test2() 执行完成,花费:{0}毫秒。" ); |
Console.WriteLine( "====================================================" ); |
Benchmarking( new Action(Test3), "Test3() 执行完成,花费:{0}毫秒。" ); |
public static void Test1() |
NonDeterministicEngine engine = new NonDeterministicEngine(); |
engine.AddParam( "a"
new int [] { 1, 2, 3, 4, 5, 6 }); |
engine.AddParam( "b"
new int [] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
engine.AddRequire(( int a) => a > 2 && a < 9); |
engine.AddRequire(( int b) => b > 5 && b <= 10); |
engine.AddRequire(( int a, int b) => a == b - 1); |
result => Console.WriteLine( "a = {0}, b = {1}" , result[ "a" ], result[ "b" ])); |
public static void Test2() |
NonDeterministicEngine engine = new NonDeterministicEngine(); |
engine.AddParam( "baker"
new int [] { 1, 2, 3, 4, 5 }); |
engine.AddParam( "cooper"
new int [] { 1, 2, 3, 4, 5 }); |
engine.AddParam( "fletcher"
new int [] { 1, 2, 3, 4, 5 }); |
engine.AddParam( "miller"
new int [] { 1, 2, 3, 4, 5 }); |
engine.AddParam( "smith"
new int [] { 1, 2, 3, 4, 5 }); |
engine.AddRequire(( int baker) => baker != 5); |
engine.AddRequire(( int cooper) => cooper != 1); |
engine.AddRequire(( int fletcher) => fletcher != 1 && fletcher != 5); |
engine.AddRequire(( int miller, int cooper) => miller > cooper); |
engine.AddRequire(( int smith, int fletcher) => |
&& smith != fletcher - 1); |
engine.AddRequire(( int fletcher, int cooper) => fletcher != cooper + 1 |
&& fletcher != cooper - 1); |
engine.AddRequire(( int baker, int cooper, int fletcher, int miller, int smith) => |
baker != cooper && baker != fletcher && baker != miller |
&& baker != smith && cooper != fletcher && cooper != miller |
&& cooper != smith && fletcher != miller && fletcher != smith && miller != smith); |
Console.WriteLine( "baker: {0}, cooper: {1}, fletcher: {2}, miller: {3}, smith: {4}"
|
public static void Test3() |
var engine = new NonDeterministicEngine(); |
engine.AddParam( "a"
new int [] { 1, 2, 3, 4, 5, 6, 7, 8 }); |
engine.AddParam( "b"
new int [] { 1, 2, 3, 4, 5, 6, 7, 8 }); |
engine.AddParam( "c"
new int [] { 1, 2, 3, 4, 5, 6, 7, 8 }); |
engine.AddParam( "d"
new int [] { 1, 2, 3, 4, 5, 6, 7, 8 }); |
engine.AddParam( "e"
new int [] { 1, 2, 3, 4, 5, 6, 7, 8 }); |
engine.AddParam( "f"
new int [] { 1, 2, 3, 4, 5, 6, 7, 8 }); |
engine.AddParam( "g"
new int [] { 1, 2, 3, 4, 5, 6, 7, 8 }); |
engine.AddParam( "h"
new int [] { 1, 2, 3, 4, 5, 6, 7, 8 }); |
engine.AddRequire(( int a, int b, int c, int d, int e, int f, int g, int h) => |
a != b && a != c && a != d |
&& a != e && a != f && a != g && a != h |
&& b != c && b != d && b != e && b != f && b != g && b != h |
&& c != d && c != e && c != f && c != g && c != h |
&& d != e && d != f && d != g && d != h |
&& e != f && e != g && e != h |
&& NotInTheSameDiagonalLine( new int [] { a, b, c, d, e, f, g, h })); |
Console.WriteLine( "(1,{0}), (2,{1}), (3,{2}), (4,{3}), (5,{4}), (6,{5}), (7,{6}), (8,{7})"
|
static bool NotInTheSameDiagonalLine( int [] cols) |
for ( int i = 0; i < cols.Length - 1; i++) |
for ( int j = i + 1; j < cols.Length; j++) |
if (j - i == Math.Abs(cols[j] - cols[i])) |
public static void Benchmarking(Action f, string messageFormat) |
DateTime time1 = DateTime.Now; |
DateTime time2 = DateTime.Now; |
Console.WriteLine(messageFormat, (time2 - time1).TotalMilliseconds); |
using System.Collections.Generic; |
using System.Collections; |
namespace NonDeterministicEngineCS |
public IEnumerator Values |
using System.Collections.Generic; |
namespace NonDeterministicEngineCS |
public abstract class Condition |
public IList< string > ParamNames |
public abstract bool Call( params object [] args); |
public Condition(Delegate predicate) |
ParamNames = predicate.Method.GetParameters().Select(p => p.Name).ToArray(); |
public class Condition<T> : Condition |
public Condition(Func<T, bool > predicate) |
public override bool Call( params object [] args) |
return m_func((T)args[0]); |
public class Condition<T1, T2> : Condition |
public Condition(Func<T1, T2, bool > predicate) |
Func<T1, T2, bool > m_func; |
public override bool Call( params object [] args) |
return m_func((T1)args[0], (T2)args[1]); |
public class Condition<T1, T2, T3> : Condition |
public Condition(Func<T1, T2, T3, bool > predicate) |
Func<T1, T2, T3, bool > m_func; |
public override bool Call( params object [] args) |
return m_func((T1)args[0], (T2)args[1], (T3)args[2]); |
public class Condition<T1, T2, T3, T4> : Condition |
public Condition(Func<T1, T2, T3, T4, bool > predicate) |
Func<T1, T2, T3, T4, bool > m_func; |
public override bool Call( params object [] args) |
return m_func((T1)args[0], (T2)args[1], (T3)args[2], (T4) args[3]); |
public class Condition<T1, T2, T3, T4, T5> : Condition |
public Condition(Func<T1, T2, T3, T4, T5, bool > predicate) |
Func<T1, T2, T3, T4, T5, bool > m_func; |
public override bool Call( params object [] args) |
return m_func((T1)args[0], (T2)args[1], (T3)args[2], (T4)args[3], (T5)args[4]); |
public class Condition<T1, T2, T3, T4, T5, T6> : Condition |
public Condition(Func<T1, T2, T3, T4, T5, T6, bool > predicate) |
Func<T1, T2, T3, T4, T5, T6, bool > m_func; |
public override bool Call( params object [] args) |
return m_func((T1)args[0], (T2)args[1], (T3)args[2], (T4)args[3], (T5)args[4], (T6)args[5]); |
public class Condition<T1, T2, T3, T4, T5, T6, T7> : Condition |
public Condition(Func<T1, T2, T3, T4, T5, T6, T7, bool > predicate) |
Func<T1, T2, T3, T4, T5, T6, T7, bool > m_func; |
public override bool Call( params object [] args) |
return m_func((T1)args[0], (T2)args[1], (T3)args[2], (T4)args[3], (T5)args[4], (T6)args[5], (T7)args[6]); |
public class Condition<T1, T2, T3, T4, T5, T6, T7, T8> : Condition |
public Condition(Func<T1, T2, T3, T4, T5, T6, T7, T8, bool > predicate) |
Func<T1, T2, T3, T4, T5, T6, T7, T8, bool > m_func; |
public override bool Call( params object [] args) |
return m_func((T1)args[0], (T2)args[1], (T3)args[2], (T4)args[3], (T5)args[4], (T6)args[5], (T7)args[6], (T8)args[7]); |
using System.Collections.Generic; |
using System.Collections; |
using System.Threading.Tasks; |
using System.Linq.Expressions; |
namespace NonDeterministicEngineCS |
public class NonDeterministicEngine |
private List<Param> m_paramDict = new List<Param>(); |
private List<Condition> m_predicateDict = new List<Condition>(); |
public void AddParam( string name, IEnumerable values) |
m_paramDict.Add( new Param { Name = name, Values = values.GetEnumerator() }); |
public void AddRequire<T>(Func<T, bool > predicate) |
m_predicateDict.Add( new Condition<T>(predicate)); |
public void AddRequire<T1, T2>(Func<T1, T2, bool > predicate) |
m_predicateDict.Add( new Condition<T1, T2>(predicate)); |
public void AddRequire<T1, T2, T3>(Func<T1, T2, T3, bool > predicate) |
m_predicateDict.Add( new Condition<T1, T2, T3>(predicate)); |
public void AddRequire<T1, T2, T3, T4>(Func<T1, T2, T3, T4, bool > predicate) |
m_predicateDict.Add( new Condition<T1, T2, T3, T4>(predicate)); |
public void AddRequire<T1, T2, T3, T4, T5>(Func<T1, T2, T3, T4, T5, bool > predicate) |
m_predicateDict.Add( new Condition<T1, T2, T3, T4, T5>(predicate)); |
public void AddRequire<T1, T2, T3, T4, T5, T6>(Func<T1, T2, T3, T4, T5, T6, bool > predicate) |
m_predicateDict.Add( new Condition<T1, T2, T3, T4, T5, T6>(predicate)); |
public void AddRequire<T1, T2, T3, T4, T5, T6, T7>(Func<T1, T2, T3, T4, T5, T6, T7, bool > predicate) |
m_predicateDict.Add( new Condition<T1, T2, T3, T4, T5, T6, T7>(predicate)); |
public void AddRequire<T1, T2, T3, T4, T5, T6, T7, T8>(Func<T1, T2, T3, T4, T5, T6, T7, T8, bool > predicate) |
m_predicateDict.Add( new Condition<T1, T2, T3, T4, T5, T6, T7, T8>(predicate)); |
public IEnumerable<Dictionary< string
object >> GetResults() |
var em = new CombinationEnumerable( this ); |
public void EachResult(Action<Dictionary< string
object >> action) |
var em = new CombinationEnumerable( this ); |
bool Satisfy(Dictionary< string
object > result) |
foreach (Condition item in m_predicateDict) |
var args = item.ParamNames.Select( |
private class CombinationEnumerable : IEnumerable<Dictionary< string
object >> |
NonDeterministicEngine m_engine; |
public CombinationEnumerable(NonDeterministicEngine engine) |
public IEnumerator<Dictionary< string
object >> GetEnumerator() |
return new CombinationEnumerator(m_engine); |
IEnumerator IEnumerable.GetEnumerator() |
return new CombinationEnumerator(m_engine); |
/// 组合多个 iterator 为一个复合的 iterator. |
/// MoveNext 实现为:移动到下一个所有变量值可能的组合。 |
private class CombinationEnumerator : IEnumerator<Dictionary< string
object >> |
private bool m_firstTime = true
|
private NonDeterministicEngine m_target; |
public CombinationEnumerator(NonDeterministicEngine engine) |
public Dictionary< string
object > GetCurrent() |
return m_target.m_paramDict.ToDictionary |
(param => param.Name, param => param.Values.Current); |
// 首次执行时,需要将所有变量的 enumerator 都前进到起始位置 |
foreach (Param item in m_target.m_paramDict) |
// 首先尝试最后一个变量的 iterator,看能否 MoveNext() (是否还有没有尝试过的值)。 |
int iterIndex = m_target.m_paramDict.Count - 1; |
bool canMoveNext = m_target.m_paramDict[iterIndex].Values.MoveNext(); |
// 否则依次回溯到前一个变量,看该变量的 iterator 能否 MoveNext() |
// 表明已尝试了所有变量的所有可能值,退无可退,则终止枚举过程。 |
canMoveNext = m_target.m_paramDict[iterIndex].Values.MoveNext(); |
// 则需要将这个位置之后的所有其他变量的 iterator 复位,并前进到第一种可能性。 |
for ( int i = iterIndex + 1; i < m_target.m_paramDict.Count; i++) |
var iter = m_target.m_paramDict[i].Values; |
foreach (var param in m_target.m_paramDict) |
public Dictionary< string
object > Current |
public bool IterationOver |
object IEnumerator.Current |
- Spark源码剖析 - 计算引擎
本章导读 RDD作为Spark对各种数据计算模型的统一抽象,被用于迭代计算过程以及任务输出结果的缓存读写.在所有MapReduce框架中,shuffle是连接map任务和reduce任务的桥梁.map ...
- 【Spark深入学习 -13】Spark计算引擎剖析
----本节内容------- 1.遗留问题解答 2.Spark核心概念 2.1 RDD及RDD操作 2.2 Transformation和Action 2.3 Spark程序架构 2.4 Spark ...
- 基于Kafka的实时计算引擎如何选择?Flink or Spark?
1.前言 目前实时计算的业务场景越来越多,实时计算引擎技术及生态也越来越成熟.以Flink和Spark为首的实时计算引擎,成为实时计算场景的重点考虑对象.那么,今天就来聊一聊基于Kafka的实时计算引 ...
- 基于Kafka的实时计算引擎如何选择?(转载)
1.前言 目前实时计算的业务场景越来越多,实时计算引擎技术及生态也越来越成熟.以Flink和Spark为首的实时计算引擎,成为实时计算场景的重点考虑对象.那么,今天就来聊一聊基于Kafka的实时计算引 ...
- 交互式计算引擎REOLAP篇
交互式计算引擎ROLAP篇 摘自:<大数据技术体系详解:原理.架构与实践> 一.Impala Impala最初由Cloudera公司开发的,其最初设计动机是充分结合传统数据库与大数据系 ...
- 腾讯大数据之TDW计算引擎解析——Shuffle
转自 https://www.csdn.net/article/2014-05-19/2819831-TDW-Shuffle/1 摘要:腾讯分布式数据仓库基于开源软件Hadoop和Hive进行构建,T ...
- Flink学习笔记-新一代Flink计算引擎
说明:本文为<Flink大数据项目实战>学习笔记,想通过视频系统学习Flink这个最火爆的大数据计算框架的同学,推荐学习课程: Flink大数据项目实战:http://t.cn/EJtKh ...
- Fel表达式计算引擎学习
转载原文地址:Fel是轻量级的高效的表达式计算引擎 Fel的问题 Fel的问题 Fel是轻量级的高效的表达式计算引擎 Fel在源自于企业项目,设计目标是为了满足不断变化的功能需求和性能需求. Fel是 ...
- 《大数据实时计算引擎 Flink 实战与性能优化》新专栏
基于 Flink 1.9 讲解的专栏,涉及入门.概念.原理.实战.性能调优.系统案例的讲解. 专栏介绍 扫码下面专栏二维码可以订阅该专栏 首发地址:http://www.54tianzhisheng. ...
随机推荐
- SqlBulkCopy效率低下原因分析
看到标题 应该会奇怪 SqlBulkCopy 为什么会效率低下 场景:接手项目 数据库SQLSERVER2008R2, 目前有一张流水表单表数据超过4亿,表中建有索引,有其他模块对这个表进行查询操作 ...
- Java可变参数以及一个简单应用
可变参数: Java1.5增加了新特性:可变参数:适用于参数个数不确定,类型确定的情况,java把可变参数当做数组处理. 注意:可变参数必须位于最后一项. 原因:当可变参数个数多余一个时,必将有一个不 ...
- 2017年十大奇葩画风的H5页面案例,原来脑洞可以这样大
每个人都是视觉动物,画面精美.体验奇特的H5,用户在内心一般都会满分打出,毫不吝啬,同时也毫不犹豫分享,因为此时的分享不掉价儿~ 今天给大家准备了十支H5,画风超级奇特,非常值得一看所有案例均可在19 ...
- 怎么用SQL语句备份和恢复数据库?
BACKUP DATABASE "mydb" TO DISK ='C:\mybak.db' with init RESTORE DATABASE "mydb" ...
- php环境搭建工具推荐
楼楼最近由于一系列原因,使用了几款php环境搭建工具,安装配置方便,所以在这里推荐一下.第一款是XAMPP(网址http://www.xampps.com/),软件包原来的名字是 LAMPP,但是为了 ...
- linux下开机不自动挂载指定分区
我的debian装好后,有保留windows,但是却不想在debian启动后桌面上,文件管理器中显示windows分区,留个记录在这里,需要的时候方便查看 使用mount 的 noauto参数: 创建 ...
- Linux入门(15)——Ubuntu16.04安装codeblocks搭建C/C++的IDE环境
安装codeblocks: sudo add-apt-repository ppa:damien-moore/codeblocks-stable sudo apt-get update sudo ap ...
- Yii2之类自动加载
在yii中,程序中需要使用到的类无需事先加载其类文件,在使用的时候才自动定位类文件位置并加载之,这么高效的运行方式得益于yii的类自动加载机制. Yii的类自动加载实际上使用的是PHP的类自动加载,所 ...
- javascript的一些算法的实用小技巧
一.交换两个数字的值 我们交换两个数字的值想到的方法一般就是用一个新的变变量,让他把一个数存起来,然后在交换两个数字的值,看下面这种. var a = 1, b = 2; //交换两个数字的值 var ...
- Android Studio 3.0 使用问题解决方案总结
问题:创建新项目非常慢 问题描述: 更新到3.0版本后,出现创建新项目一直停留在如下图的界面: 选择等待?不知道要等到什么时候,这时候怎么办呢?显然,不能一直等待下去呀,需要想办法让他能尽快的加载好才 ...