Skip to content

Instantly share code, notes, and snippets.

View Sergio0694's full-sized avatar
🚀
Coding all day

Sergio Pedri Sergio0694

🚀
Coding all day
View GitHub Profile
@Sergio0694
Sergio0694 / tf_keras_error_repro.py
Created July 11, 2018 13:29
Reproduces an error when loading multiple shared instances of a Keras model in the same scope
import tensorflow as tf
'''
This snippet reproduces an error when trying to load multiple shared instances
of a Keras model in TensorFlow, when accessing the same scope multiple times.
Creating multiple instances repeatedly in a single step works.
'''
def load_vgg19_multiple(tensors):
'''Creates n shared instances of VGG19, in a single run.'''
@Sergio0694
Sergio0694 / GenericOperatorPattern.md
Last active March 16, 2019 17:20
A pattern to work around the lack of static, virtual generic interface methods in C#

The Generic Operator pattern

The Generic Operator pattern (GO pattern, for short) works around two limitations in C#:

  • The lack of static interface methods
  • The lack of virtual static methods (eg. static methods that can be inherited and overridden)

The first one is pretty easy to demonstrate:

public interface IDoThings
@Sergio0694
Sergio0694 / ComputeSharpBokehTest.cs
Created August 28, 2019 15:19
A benchmark between ImageSharp and ComputeSharp with a bokeh effect
using System;
using System.IO;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using ComputeSharp;
using SixLabors.ImageSharp;
| Method | Mean | Error | StdDev | Ratio |
|------------------------ |------------:|-----------:|-----------:|------:|
| ReflectionSmall | 954.36 ms | 11.8428 ms | 11.0778 ms | 1.00 |
| ILGetterSmall | 678.82 ms | 4.5664 ms | 3.8132 ms | 0.71 |
| UnwrappedILGetterSmall | 661.00 ms | 5.2797 ms | 4.6803 ms | 0.69 |
| SingleILGetterSmall | 65.24 ms | 0.3079 ms | 0.2880 ms | 0.07 |
| | | | | |
| ReflectionMedium | 1,427.80 ms | 9.2508 ms | 8.6532 ms | 1.00 |
| ILGetterMedium | 1,023.99 ms | 6.6233 ms | 6.1954 ms | 0.72 |
| UnwrappedILGetterMedium | 1,011.03 ms | 2.6657 ms | 2.3631 ms | 0.71 |
public static unsafe (object[] References, byte[] Bytes) GetData(
Delegate instance, DataLoader loader,
int referenceCount, int byteSize)
{
// Reference and byte array
object[] refs = ArrayPool<object>.Shared.Rent(referenceCount);
byte[] bytes = ArrayPool<byte>.Shared.Rent(byteSize);
ref object r0 = ref refs.Length > 0 ? ref refs[0] : ref Unsafe.AsRef<object>(null);
ref byte r1 = ref bytes.Length > 0 ? ref bytes[0] : ref Unsafe.AsRef<byte>(null);
public static void EmitStoreToAddress(this ILGenerator il, Type type)
{
if (type.IsValueType)
{
// Pick the optimal opcode to set a value type
OpCode opcode = Marshal.SizeOf(type) switch
{
// Use the faster op codes for sizes <= 8
1 when type == typeof(byte) || type == typeof(sbyte) => OpCodes.Stind_I1,
2 when type == typeof(short) || type == typeof(ushort) => OpCodes.Stind_I2,
public static void EmitAddOffset(this ILGenerator il, int offset)
{
// Push the offset to the stack
if (offset <= 8)
{
il.Emit(offset switch
{
0 => OpCodes.Ldc_I4_0,
1 => OpCodes.Ldc_I4_1,
2 => OpCodes.Ldc_I4_2,
public static void Main()
{
int[] array = new int[100];
{
int value = 1;
Action<int> action = i => array[i] = value;
}
}
public static void EmitStoreLocal(this ILGenerator il, int index)
{
if (index <= 3)
{
il.Emit(index switch
{
0 => OpCodes.Stloc_0,
1 => OpCodes.Stloc_1,
2 => OpCodes.Stloc_2,
3 => OpCodes.Stloc_3,
public static Func<object, object> BuildDynamicGetter(ClosureField field)
{
// Create a new dynamic method
FieldInfo[] hierarchy = field.Parents.Append(field.Info).ToArray();
Type ownerType = hierarchy[0].DeclaringType;
DynamicMethod method = new DynamicMethod(
$"Get{field.Info.Name}",
typeof(object), // The return type
new[] { typeof(object) }, // A single object parameter
ownerType); // The type that will own the new method