Laszlo

Hello, I am Laszlo

Software-Engineer, .NET developer

Contact Me

SIMD Gather and Scatter Anagram

Introduction

One of the most difficult problems with SIMD is handling non-contiguous memory access. To address this challenge AVX-512 adds gather and scatter instructions to load and store memory in an array at non-adjacent indexes. These instructions enable a whole new set of algorithms to be vectorized using SIMD operations.

Gather is a single instruction that loads data from non-adjacent indexes of an array into a Vector register. Scatter is a single instruction that stores data at non-adjacent indexes to an array from a Vector register.

Both instructions have a source/destination register parameter, a reference to an array parameter, and another vector parameter containing the indexes for each lane to be loaded or stored.

Find out more »


Using Prioritized Channel

In .NET 9, a new UnboundedPrioritized channel type has been introduced to System.Threading.Channels. This feature has been available since version 8 of the Channel's NuGet package and is compatible with older .NET versions.

Channels provide thread-safe data structures for producer/consumer scenarios. In this pattern, one or more producers add items to a channel while one or more consumers read from it independently.

Two types of channels exist:

  • Bounded channels: Have a maximum size limit with customizable behavior when full
  • Unbounded channels: Have no size limit (beyond system memory constraints)

Find out more »


Input Parsing to Known Value

A common task for Line of Business (LOB) applications is parsing an input string into an internal identifier. This blog post uses .NET 10 code samples. For simplicity, let's assume the inputs are non-malicious in terms of length, values, culture, etc.

Suppose you have a string input that needs to be parsed into one of the following enums:

public enum AccessLevel
{
    NONE,
    READONLY,
    READWRITE,
    CREATE,
    DELETE,
    MANAGE_USER,
    CONFIGURE_SYSTEM,
    FULL_CONTROL
}

I chose the enum names to be in uppercase ("shouting"). While this casing is not typical for C#, many applications define domain-specific terms in uppercase to match business terminology. If business analysts use uppercase names, the enums often follow suit.

Find out more »


IsSorted using SIMD in .NET

Sorting a set or an array is a relatively expensive operation. The costs of sorting typically increase non-linearly with the input size. Therefore, in certain cases, it can be beneficial to check if an array is already sorted before attempting to sort it.

Note: Different sorting algorithms handle sorted or 'nearly sorted' collections with varying degrees of efficiency.

For perspective, sorting an already sorted integer array with a million elements using Array.Sort in .NET takes 5,180.9 us on my machine. In contrast, validating if the same array is sorted takes only 119.0 us. For applications where most input arrays are expected to be sorted, validating sorted-ness first can be a worthwhile optimization.

Similarly, an operation like binary search might want to validate the precondition of the input array being sorted.

Find out more »


Measuring Lock Contention

Scaling multi-threaded applications is often limited by the proportion of the workload that cannot be parallelized. This concept is captured by Amdahl's law. Code sections guarded by locks are a common example — they restrict scalability by allowing only one thread (or n threads in the case of semaphores) to execute, forcing other threads to wait due to lock contention.

Context

In an HTTP/2 server, requests and responses on a connection are multiplexed. The server needs to write concurrently computed responses to a network stream. Such multiplexing can be achieved in multiple ways:

Find out more »