NEO Vm原理及其实现

简介及与evm主要区别

neo vm和evm类似。底层都实现了一套opcode以及对应的执行器,opcode设计差距蛮大的,总体上来说evm的更加简洁,neo vm的功能更加丰富强大。

  1. neo底层原生支持类型系统,所有栈上的内容都是有类型的,而在evm中所有的栈上内容都是无类型的,依赖于运行时转换。实质上在于空间和时间的取舍。

  2. neo在opcode级别支持类型及其操作,在内部函数调用方面evm通过jumpdest解决,neo vm的jump类指令则仅用于循环,函数调用则通过call和systemcall解决(这样很好的支持了调用函数栈)。总的来说neo vm一些高级操作可以下沉到code级别执行,方便了代码的转换。而evm则更加考验编译器的能力。

  3. 隔离执行器和外部对象的具体实现,vm提供了一些外部接口用于执行一些和外部对象和存储相关的操作。eth的外部对象和指令揉合在一起。

  4. 理论上来说eth也可以支持多种语言,实际上来说solidity一家独大,其中未尝没有eth的opcode转换难度大的原因,而neo vm的opcode则相对友好,支持多种语言开发。当然evm也并非没有好处,solidity支持内联编程,如果熟悉evm的opcode能写出效率非常高的合约。neo在这方面尚未提供支持。

  5. neo vm支持debug,支持step into,step over,break point operation。

如需了解evm的详细实现可以参考另一篇博文 https://my.oschina.net/hunjixin/blog/1805306

代码结构

  1. .
  2. ├── ExecutionContext.cs //执行上下文 引擎,代码,断点
  3. ├── ExecutionEngine.cs //执行引擎
  4. ├── Helper.cs //编码及long型
  5. ├── ICrypto.cs //加密解密
  6. ├── IInteropInterface.cs //外部对象相关
  7. ├── InteropService.cs //存储相关
  8. ├── IScriptContainer.cs //脚本
  9. ├── IScriptTable.cs //脚本读取
  10. ├── neo-vm.csproj
  11. ├── OpCode.cs //操作码
  12. ├── RandomAccessStack.cs //快速访问栈
  13. ├── ScriptBuilder.cs //脚本构建
  14. ├── StackItem.cs //栈
  15. ├── Types //类型
  16. ├── Array.cs //数组
  17. ├── Boolean.cs //bool
  18. ├── ByteArray.cs //比特数组
  19. ├── Integer.cs //整数
  20. ├── InteropInterface.cs //操作对象接口
  21. ├── Map.cs //映射
  22. └── Struct.cs //结构体
  23. └── VMState.cs //执行状态

类型系统

vm支持七种类型,分别是数组,bool,byte数组,整数,外部对象,映射,结构体。所有的结构体都是继承子StackItem,同时具有自己的数据字段。

stackItem

  1. public abstract class StackItem : IEquatable<StackItem>
  2. {
  3. public abstract bool Equals(StackItem other);
  4.  
  5. public sealed override bool Equals(object obj)
  6. {
  7. if (obj == null) return false;
  8. if (obj == this) return true;
  9. if (obj is StackItem other)
  10. return Equals(other);
  11. return false;
  12. }
  13.  
  14. public static StackItem FromInterface(IInteropInterface value)
  15. {
  16. return new InteropInterface(value);
  17. }
  18.  
  19. public virtual BigInteger GetBigInteger()
  20. {
  21. return new BigInteger(GetByteArray());
  22. }
  23.  
  24. public virtual bool GetBoolean()
  25. {
  26. return GetByteArray().Any(p => p != );
  27. }
  28.  
  29. public abstract byte[] GetByteArray();
  30.  
  31. public override int GetHashCode()
  32. {
  33. unchecked
  34. {
  35. int hash = ;
  36. foreach (byte element in GetByteArray())
  37. hash = hash * + element;
  38. return hash;
  39. }
  40. }
  41.  
  42. public virtual string GetString()
  43. {
  44. return Encoding.UTF8.GetString(GetByteArray());
  45. }
  46.  
  47. public static implicit operator StackItem(int value)
  48. {
  49. return (BigInteger)value;
  50. }
  51.  
  52. public static implicit operator StackItem(uint value)
  53. {
  54. return (BigInteger)value;
  55. }
  56.  
  57. public static implicit operator StackItem(long value)
  58. {
  59. return (BigInteger)value;
  60. }
  61.  
  62. public static implicit operator StackItem(ulong value)
  63. {
  64. return (BigInteger)value;
  65. }
  66.  
  67. public static implicit operator StackItem(BigInteger value)
  68. {
  69. return new Integer(value);
  70. }
  71.  
  72. public static implicit operator StackItem(bool value)
  73. {
  74. return new Boolean(value);
  75. }
  76.  
  77. public static implicit operator StackItem(byte[] value)
  78. {
  79. return new ByteArray(value);
  80. }
  81.  
  82. public static implicit operator StackItem(StackItem[] value)
  83. {
  84. return new Array(value);
  85. }
  86.  
  87. public static implicit operator StackItem(List<StackItem> value)
  88. {
  89. return new Array(value);
  90. }
  91. }

bool 为例子

  1. public class Boolean : StackItem
  2. {
  3. private static readonly byte[] TRUE = { };
  4. private static readonly byte[] FALSE = new byte[];
  5.  
  6. private bool value;
  7.  
  8. public Boolean(bool value)
  9. {
  10. this.value = value;
  11. }
  12.  
  13. public override bool Equals(StackItem other)
  14. {
  15. if (ReferenceEquals(this, other)) return true;
  16. if (ReferenceEquals(null, other)) return false;
  17. if (other is Boolean b) return value == b.value;
  18. byte[] bytes_other;
  19. try
  20. {
  21. bytes_other = other.GetByteArray();
  22. }
  23. catch (NotSupportedException)
  24. {
  25. return false;
  26. }
  27. return GetByteArray().SequenceEqual(bytes_other);
  28. }
  29.  
  30. public override BigInteger GetBigInteger()
  31. {
  32. return value ? BigInteger.One : BigInteger.Zero;
  33. }
  34.  
  35. public override bool GetBoolean()
  36. {
  37. return value;
  38. }
  39.  
  40. public override byte[] GetByteArray()
  41. {
  42. return value ? TRUE : FALSE;
  43. }
  44. }

opecode

贴一些上来感受下

数值常量

  1. PUSH2 = 0x52, // The number 2 is pushed onto the stack.
  2. PUSH3 = 0x53, // The number 3 is pushed onto the stack.
  3. PUSH4 = 0x54, // The number 4 is pushed onto the stack.
  4. PUSH5 = 0x55, // The number 5 is pushed onto the stack.

跳转

  1. JMP = 0x62,
  2. JMPIF = 0x63,
  3. JMPIFNOT = 0x64,

调用

  1. CALL = 0x65,
  2. RET = 0x66,
  3. APPCALL = 0x67,
  4. SYSCALL = 0x68,
  5. TAILCALL = 0x69,

栈操作,neo再着一块的相对比较丰富(这里并不是全部)

  1. DROP = 0x75, // Removes the top stack item.
  2. DUP = 0x76, // Duplicates the top stack item.
  3. PICK = 0x79, // The item n back in the stack is copied to the top.
  4. ROLL = 0x7A, // The item n back in the stack is moved to the top.
  5. SWAP = 0x7C, // The top two items on the stack are swapped.

运算,仅贴了些代表性的上来

  1. INC = 0x8B, // 1 is added to the input.
  2. SIGN = 0x8D,
  3. ABS = 0x90, // The input is made positive.
  4. NZ = 0x92, // Returns 0 if the input is 0. 1 otherwise.
  5. DIV = 0x96, // a is divided by b.
  6. MOD = 0x97, // Returns the remainder after dividing a by b.
  7. SHR = 0x99, // Shifts a right b bits, preserving sign.
  8. BOOLAND = 0x9A, // If both a and b are not 0, the output is 1. Otherwise 0.
  9. GTE = 0xA2, // Returns 1 if a is greater than or equal to b, 0 otherwise.
  10. MAX = 0xA4, // Returns the larger of a and b.
  11. WITHIN = 0xA5, // Returns 1 if x is within the specified range (left-inclusive), 0 otherwise.

加密验证

  1. SHA1 = 0xA7, // The input is hashed using SHA-1.
  2. SHA256 = 0xA8, // The input is hashed using SHA-256.
  3. HASH160 = 0xA9,
  4. HASH256 = 0xAA,
  5. CHECKSIG = 0xAC,
  6. VERIFY = 0xAD,
  7. CHECKMULTISIG = 0xAE,

数组,结构体及相关操作

  1. ARRAYSIZE = 0xC0,
  2. PACK = 0xC1,
  3. UNPACK = 0xC2,
  4. PICKITEM = 0xC3,
  5. SETITEM = 0xC4,
  6. NEWARRAY = 0xC5, //用作引用類型
  7. NEWSTRUCT = 0xC6, //用作值類型
  8. NEWMAP = 0xC7,
  9. APPEND = 0xC8,
  10. REVERSE = 0xC9,
  11. REMOVE = 0xCA,
  12. HASKEY = 0xCB,
  13. KEYS = 0xCC,
  14. VALUES = 0xCD,

异常

  1. THROW = 0xF0,
  2. THROWIFNOT = 0xF1

外部接口

脚本容器,保存当前执行脚本

  1. public interface IScriptContainer : IInteropInterface
  2. {
  3. byte[] GetMessage();
  4. }

合约脚本查找

  1. public interface IScriptTable
  2. {
  3. byte[] GetScript(byte[] script_hash);
  4. }

加密

  1. public interface ICrypto
  2. {
  3. byte[] Hash160(byte[] message);
  4.  
  5. byte[] Hash256(byte[] message);
  6.  
  7. bool VerifySignature(byte[] message, byte[] signature, byte[] pubkey);
  8. }

外部服务调用接口

  1. public class InteropService
  2. {
  3. private Dictionary<string, Func<ExecutionEngine, bool>> dictionary = new Dictionary<string, Func<ExecutionEngine, bool>>();
  4.  
  5. public InteropService()
  6. {
  7. Register("System.ExecutionEngine.GetScriptContainer", GetScriptContainer);
  8. Register("System.ExecutionEngine.GetExecutingScriptHash", GetExecutingScriptHash);
  9. Register("System.ExecutionEngine.GetCallingScriptHash", GetCallingScriptHash);
  10. Register("System.ExecutionEngine.GetEntryScriptHash", GetEntryScriptHash);
  11. }
  12.  
  13. protected void Register(string method, Func<ExecutionEngine, bool> handler)
  14. {
  15. dictionary[method] = handler;
  16. }
  17.  
  18. internal bool Invoke(string method, ExecutionEngine engine)
  19. {
  20. if (!dictionary.TryGetValue(method, out Func<ExecutionEngine, bool> func)) return false;
  21. return func(engine);
  22. }
  23.  
  24. private static bool GetScriptContainer(ExecutionEngine engine)
  25. {
  26. engine.EvaluationStack.Push(StackItem.FromInterface(engine.ScriptContainer));
  27. return true;
  28. }
  29.  
  30. private static bool GetExecutingScriptHash(ExecutionEngine engine)
  31. {
  32. engine.EvaluationStack.Push(engine.CurrentContext.ScriptHash);
  33. return true;
  34. }
  35.  
  36. private static bool GetCallingScriptHash(ExecutionEngine engine)
  37. {
  38. engine.EvaluationStack.Push(engine.CallingContext.ScriptHash);
  39. return true;
  40. }
  41.  
  42. private static bool GetEntryScriptHash(ExecutionEngine engine)
  43. {
  44. engine.EvaluationStack.Push(engine.EntryContext.ScriptHash);
  45. return true;
  46. }
  47. }

外部对象接口

  1. public interface IInteropInterface
  2. {
  3. }

执行器

  1. public class ExecutionEngine : IDisposable
  2. {
  3. //调用栈
  4. public RandomAccessStack<ExecutionContext> InvocationStack { get; } = new RandomAccessStack<ExecutionContext>();
  5. //执行栈
  6. public RandomAccessStack<StackItem> EvaluationStack { get; } = new RandomAccessStack<StackItem>();
  7. //参数栈
  8. public RandomAccessStack<StackItem> AltStack { get; } = new RandomAccessStack<StackItem>();
  9. public ExecutionContext CurrentContext => InvocationStack.Peek();
  10. public ExecutionContext CallingContext => InvocationStack.Count > ? InvocationStack.Peek() : null;
  11. public ExecutionContext EntryContext => InvocationStack.Peek(InvocationStack.Count - );
  12. //执行状态
  13. public VMState State { get; protected set; } = VMState.BREAK;
  14.  
  15. //载入执行脚本
  16. void LoadScript(byte[] script, bool push_only = false){}
  17. //添加断点
  18. void AddBreakPoint(uint position){}
  19. //删除断点
  20. bool RemoveBreakPoint(uint position){}
  21.  
  22. //执行脚本
  23. void Execute(){}
  24. //执行opcode
  25. void ExecuteOp(OpCode opcode, ExecutionContext context){}
  26.  
  27. //执行下一步
  28. void StepInto(){}
  29. //当前call执行完成
  30. void StepOut(){}
  31. //全部执行
  32. void StepOver(){}
  33. }

操作符号执行过程

  1. private void ExecuteOp(OpCode opcode, ExecutionContext context)
  2. {
  3. if (opcode > OpCode.PUSH16 && opcode != OpCode.RET && context.PushOnly)
  4. {
  5. State |= VMState.FAULT;
  6. return;
  7. }
  8. if (opcode >= OpCode.PUSHBYTES1 && opcode <= OpCode.PUSHBYTES75)
  9. EvaluationStack.Push(context.OpReader.ReadBytes((byte)opcode));
  10. else
  11. switch (opcode)
  12. {
  13. //常量push
  14. case OpCode.PUSH1:
  15. case OpCode.PUSH16:
  16. EvaluationStack.Push((int)opcode - (int)OpCode.PUSH1 + );
  17. break;
  18. case OpCode.JMP: //跳转
  19. {
  20. int offset = context.OpReader.ReadInt16();
  21. offset = context.InstructionPointer + offset - ;
  22. if (offset < || offset > context.Script.Length)
  23. {
  24. State |= VMState.FAULT;
  25. return;
  26. }
  27. bool fValue = true;
  28. if (opcode > OpCode.JMP)
  29. {
  30. fValue = EvaluationStack.Pop().GetBoolean();
  31. if (opcode == OpCode.JMPIFNOT)
  32. fValue = !fValue;
  33. }
  34. if (fValue)
  35. context.InstructionPointer = offset;
  36. }
  37. break;
  38. case OpCode.CALL: //和systemcall差不多, 区别在于system是系统预先注册的函数 call调用的是用户自己写的函数
  39. InvocationStack.Push(context.Clone());
  40. context.InstructionPointer += ;
  41. ExecuteOp(OpCode.JMP, CurrentContext);
  42. break;
  43. case OpCode.RET: //退出当前函数栈
  44. InvocationStack.Pop().Dispose();
  45. if (InvocationStack.Count == )
  46. State |= VMState.HALT;
  47. break;
  48. case OpCode.APPCALL: //调用外部合约
  49. case OpCode.TAILCALL:
  50. {
  51. if (table == null)
  52. {
  53. State |= VMState.FAULT;
  54. return;
  55. }
  56.  
  57. byte[] script_hash = context.OpReader.ReadBytes();
  58. if (script_hash.All(p => p == ))
  59. {
  60. script_hash = EvaluationStack.Pop().GetByteArray();
  61. }
  62.  
  63. byte[] script = table.GetScript(script_hash);
  64. if (script == null)
  65. {
  66. State |= VMState.FAULT;
  67. return;
  68. }
  69. if (opcode == OpCode.TAILCALL)
  70. InvocationStack.Pop().Dispose();
  71. LoadScript(script);
  72. }
  73. break;
  74. case OpCode.SYSCALL: //内部合约函数调用
  75. if (!service.Invoke(Encoding.ASCII.GetString(context.OpReader.ReadVarBytes()), this))
  76. State |= VMState.FAULT;
  77. break;
  78. case OpCode.DROP: //移除栈顶
  79. EvaluationStack.Pop();
  80. break;
  81. case OpCode.DUP: //赋值栈顶 有对应按位置复制的指令
  82. EvaluationStack.Push(EvaluationStack.Peek());
  83. break;
  84. case OpCode.EQUAL: //判等
  85. {
  86. StackItem x2 = EvaluationStack.Pop();
  87. StackItem x1 = EvaluationStack.Pop();
  88. EvaluationStack.Push(x1.Equals(x2));
  89. }
  90. break;
  91.  
  92. // Numeric
  93. case OpCode.ABS: //运算 加减乘除 最大值最小值等等
  94. {
  95. BigInteger x = EvaluationStack.Pop().GetBigInteger();
  96. EvaluationStack.Push(BigInteger.Abs(x));
  97. }
  98. break;
  99. // Crypto
  100. case OpCode.SHA256: //加密
  101. using (SHA256 sha = SHA256.Create())
  102. {
  103. byte[] x = EvaluationStack.Pop().GetByteArray();
  104. EvaluationStack.Push(sha.ComputeHash(x));
  105. }
  106. break;
  107. case OpCode.CHECKSIG: //验证
  108. {
  109. byte[] pubkey = EvaluationStack.Pop().GetByteArray();
  110. byte[] signature = EvaluationStack.Pop().GetByteArray();
  111. try
  112. {
  113. EvaluationStack.Push(Crypto.VerifySignature(ScriptContainer.GetMessage(), signature, pubkey));
  114. }
  115. catch (ArgumentException)
  116. {
  117. EvaluationStack.Push(false);
  118. }
  119. }
  120. break;
  121. // Array
  122. case OpCode.PICKITEM: //数组映射取值
  123. {
  124. StackItem key = EvaluationStack.Pop();
  125. if (key is ICollection)
  126. {
  127. State |= VMState.FAULT;
  128. return;
  129. }
  130. switch (EvaluationStack.Pop())
  131. {
  132. case VMArray array:
  133. int index = (int)key.GetBigInteger();
  134. if (index < || index >= array.Count)
  135. {
  136. State |= VMState.FAULT;
  137. return;
  138. }
  139. EvaluationStack.Push(array[index]);
  140. break;
  141. case Map map:
  142. if (map.TryGetValue(key, out StackItem value))
  143. {
  144. EvaluationStack.Push(value);
  145. }
  146. else
  147. {
  148. State |= VMState.FAULT;
  149. return;
  150. }
  151. break;
  152. default:
  153. State |= VMState.FAULT;
  154. return;
  155. }
  156. }
  157. break;
  158. case OpCode.SETITEM: //数组 映射赋值
  159. {
  160. StackItem value = EvaluationStack.Pop();
  161. if (value is Struct s) value = s.Clone();
  162. StackItem key = EvaluationStack.Pop();
  163. if (key is ICollection)
  164. {
  165. State |= VMState.FAULT;
  166. return;
  167. }
  168. switch (EvaluationStack.Pop())
  169. {
  170. case VMArray array:
  171. int index = (int)key.GetBigInteger();
  172. if (index < || index >= array.Count)
  173. {
  174. State |= VMState.FAULT;
  175. return;
  176. }
  177. array[index] = value;
  178. break;
  179. case Map map:
  180. map[key] = value;
  181. break;
  182. default:
  183. State |= VMState.FAULT;
  184. return;
  185. }
  186. }
  187. break;
  188. case OpCode.NEWARRAY: //创建数组
  189. {
  190. int count = (int)EvaluationStack.Pop().GetBigInteger();
  191. List<StackItem> items = new List<StackItem>(count);
  192. for (var i = ; i < count; i++)
  193. {
  194. items.Add(false);
  195. }
  196. EvaluationStack.Push(new Types.Array(items));
  197. }
  198. break;
  199. case OpCode.NEWSTRUCT: //创建结构体
  200. {
  201. int count = (int)EvaluationStack.Pop().GetBigInteger();
  202. List<StackItem> items = new List<StackItem>(count);
  203. for (var i = ; i < count; i++)
  204. {
  205. items.Add(false);
  206. }
  207. EvaluationStack.Push(new VM.Types.Struct(items));
  208. }
  209. break;
  210. case OpCode.NEWMAP: //创建映射
  211. EvaluationStack.Push(new Map());
  212. break;
  213. case OpCode.APPEND: //追加元素
  214. {
  215. StackItem newItem = EvaluationStack.Pop();
  216. if (newItem is Types.Struct s)
  217. {
  218. newItem = s.Clone();
  219. }
  220. StackItem arrItem = EvaluationStack.Pop();
  221. if (arrItem is VMArray array)
  222. {
  223. array.Add(newItem);
  224. }
  225. else
  226. {
  227. State |= VMState.FAULT;
  228. return;
  229. }
  230. }
  231. break;
  232. case OpCode.REMOVE: //移除元素
  233. {
  234. StackItem key = EvaluationStack.Pop();
  235. if (key is ICollection)
  236. {
  237. State |= VMState.FAULT;
  238. return;
  239. }
  240. switch (EvaluationStack.Pop())
  241. {
  242. case VMArray array:
  243. int index = (int)key.GetBigInteger();
  244. if (index < || index >= array.Count)
  245. {
  246. State |= VMState.FAULT;
  247. return;
  248. }
  249. array.RemoveAt(index);
  250. break;
  251. case Map map:
  252. map.Remove(key);
  253. break;
  254. default:
  255. State |= VMState.FAULT;
  256. return;
  257. }
  258. }
  259. break;
  260. case OpCode.KEYS: //获取映射键集合,对应的还有获取值集合 haskey
  261. switch (EvaluationStack.Pop())
  262. {
  263. case Map map:
  264. EvaluationStack.Push(new VMArray(map.Keys));
  265. break;
  266. default:
  267. State |= VMState.FAULT;
  268. return;
  269. }
  270. break;
  271.  
  272. // Exceptions
  273. case OpCode.THROW: //异常中止
  274. State |= VMState.FAULT;
  275. return;
  276. case OpCode.THROWIFNOT:
  277. if (!EvaluationStack.Pop().GetBoolean())
  278. {
  279. State |= VMState.FAULT;
  280. return;
  281. }
  282. break;
  283.  
  284. default:
  285. State |= VMState.FAULT;
  286. return;
  287. }
  288. if (!State.HasFlag(VMState.FAULT) && InvocationStack.Count > )
  289. {
  290. //断点起效的位置
  291. if (CurrentContext.BreakPoints.Contains((uint)CurrentContext.InstructionPointer))
  292. State |= VMState.BREAK;
  293. }
  294. }

转载自 https://my.oschina.net/hunjixin/blog/1812516

  1.  

NEO VM原理及其实现(转载)的更多相关文章

  1. JAVA CAS原理深度分析-转载

    参考文档: http://www.blogjava.net/xylz/archive/2010/07/04/325206.html http://blog.hesey.net/2011/09/reso ...

  2. NET/ASP.NET Routing路由(深入解析路由系统架构原理)(转载)

    NET/ASP.NET Routing路由(深入解析路由系统架构原理) 阅读目录: 1.开篇介绍 2.ASP.NET Routing 路由对象模型的位置 3.ASP.NET Routing 路由对象模 ...

  3. JMeter使用中遇到的问题:Jmeter Debug - "Unrecognized VM option '+HeapDumpOnOutOfMemoryError"(转载)

    转载自 http://www.cnblogs.com/yangxia-test 启动JMeter.bat的程序时,出现以下出错信息: Unrecognized VM option '+HeapDump ...

  4. mysql 索引原理及查询优化 -转载

    转载自 mysql 索引原理及查询优化 https://www.cnblogs.com/panfb/p/8043681.html 潘红伟   mysql 索引原理及查询优化 一 介绍 为何要有索引? ...

  5. Redis集群的原理和搭建(转载)

    转载来源:https://www.jianshu.com/p/c869feb5581d Redis集群的原理和搭建 前言 Redis 是我们目前大规模使用的缓存中间件,由于它强大高效而又便捷的功能,得 ...

  6. 深入浅出Java并发包—CountDownLauch原理分析 (转载)

    转载地址:http://yhjhappy234.blog.163.com/blog/static/3163283220135875759265/ CountDownLauch是Java并发包中的一个同 ...

  7. JPEG原理详解 (转载)

    JPEG算法解密 by jinchao   图片压缩有多重要,可能很多人可能并没有一个直观上的认识,举个例子,一张800X800大小的普通图片,如果未经压缩,大概在1.7MB左右,这个体积如果存放文本 ...

  8. 弱类型变量原理探究(转载 http://www.csdn.net/article/2014-09-15/2821685-exploring-of-the-php)

    N首页> 云计算 [问底]王帅:深入PHP内核(一)——弱类型变量原理探究 发表于2014-09-19 09:00| 13055次阅读| 来源CSDN| 36 条评论| 作者王帅 问底PHP王帅 ...

  9. DPM(Deformable Parts Model)--原理(一)(转载)

    DPM(Deformable Parts Model) Reference: Object detection with discriminatively trained partbased mode ...

随机推荐

  1. 数据标准化+网格搜索+交叉验证+预测(Python)

    Download datasets iris_training.csv from:https://github.com/tensorflow/tensorflow/tree/master/tensor ...

  2. 一、I/O操作(File文件对象)

    一.File类 Java里,文件和文件夹都是用File代表 1.使用绝对路径或者相对路径创建File对象 使用绝对路径或者相对路径创建File对象 package File; import java. ...

  3. Linux安装配置NFS教程(CentOS 6.5)

    一.服务端安装nfs 1.1安装 yum install -y rpcbind yum install -y nfs-utils 1.2配置nfs共享目录 这里以/nfs目录为例 mkdir /nfs ...

  4. java 常用命令

    #查看堆使用情况jmap -heap [pid]#查看占用内存高的对象jmap -histo:live [pid] | head -n 100#查看占用内存高的对象,dump成文件,线下分析jmap ...

  5. 码云git使用一(上传本地项目到码云git服务器上)

    主要讲下如果将项目部署到码云git服务器上,然后使用studio导入git项目,修改本地代码后,并同步到码云git上面. 首先:我们在码云上注册账号并登陆.官网(https://git.oschina ...

  6. python ctrl+c

    #!/usr/bin/env pythonimport signalimport sysimport osdef signal_handler(signal, frame): print('You p ...

  7. windows中mysql5.7保存emoji表情

    1.找到my.ini文件,修改一下配置: [client] default-character-set=utf8mb4 [mysqld] character-set-client-handshake ...

  8. 输出前n大的数(分治)

    描述:给定一个数组包含n个元素,统计前m大的数并且把这m个数从大到小输 出. 输入: 第一行包含一个整数n,表示数组的大小.n < 100000.第二行包含n个整数,表示数组的元素,整数之间以一 ...

  9. AI工具(矩形工具)(椭圆工具的操作与矩形类似)(剪切蒙版)5.11

    矩形工具:按住SHIFT键,可以绘制一个正方形. 按住ALT键,可以绘制以落点为中心的矩形. 同时按住SHIFT和ALT键可以绘制以鼠标落点为中心的正方形. 选择矩形工具,点击页面,输入高宽,精确绘制 ...

  10. SQL 常用判断语句

    我们在做sql更新时,为防止sql重复执行报错,需要对所需要执行的对象进行判断是否存在: 常用判断脚本如下: 判断视图是否存在 IF object_id('viewname') IS not NULL ...