preciz

preciz

The main idea of this library is to use :atomics as a matrix with all its benefits preserved.

iex> matrax = Matrax.new(7, 4, seed_fun: fn _, {row, col} -> row + col end)
iex> matrax |> Matrax.put({0, 0}, 1989) # atomics are mutable
iex> matrax |> Matrax.to_list_of_lists()
[
    [1989, 1, 2, 3],
    [1, 2, 3, 4],
    [2, 3, 4, 5],
    [3, 4, 5, 6],
    [4, 5, 6, 7],
    [5, 6, 7, 8],
    [6, 7, 8, 9]
]

All :atomics functions are wrapped and a few matrix specific functions are provided:

API summary

See https://hexdocs.pm/matrax for full documentation.

  • Matrax.new/2 - Create new matrix.
  • Matrax.get/2 - Returns the integer at the given position.
  • Matrax.put/3 - Puts the given integer into the given position.
  • Matrax.add/3 - Adds the given increment to the value at given position atomically.
  • Matrax.add_get/3 - Adds the given increment to the value at given position atomically and returns result.
  • Matrax.sub/3 - Subtracts the given decrement to the value at given position atomically.
  • Matrax.sub_get/3 - Subtracts the given decrement to the value at given position atomically and returns result.
  • Matrax.exchange/3 - Exchanges the given integer at the given position atomically.
  • Matrax.compare_exchange/4 - Compares & exchanges the given integer at the given position atomically.
  • Matrax.index_to_position/2 - Converts the given atomics index to position tuple.
  • Matrax.position_to_index/2 - Converts the given position tuple to atomics index.
  • Matrax.min/1 - Returns smallest integer in matrix.
  • Matrax.max/1 - Returns largest integer in matrix.
  • Matrax.sum/1 - Returns sum of integers in matrix.
  • Matrax.member?/2 - Checks if value exists within matrix.
  • Matrax.apply/2 - Applies the given function to all elements of matrix.
  • Matrax.to_list/1 - Converts matrix to a flat list.
  • Matrax.to_list_of_lists/1 - Converts matrix to list of lists.
  • Matrax.row_to_list/2 - Converts row at given index of matrix to list.
  • Matrax.column_to_list/2 - Converts column at given index of matrix to list.
  • Matrax.transpose/1 - Transposes the given matrix. (access path modification only)
  • Matrax.copy/1 - Returns a copy of the matrix with a new atomics reference. Can be used to finish transpose.
  • Matrax.submatrix/3 - Returns a new submatrix. Creates new atomics and copies values over.

GitHub: GitHub - preciz/matrax: A matrix library in pure Elixir based on atomics. · GitHub

What is the use case?
An example use case is when you need concurrent access to a matrix of integers / bitmasks.
(my use case was a constraint solving algorithm)

:atomics "utilizes only atomic hardware instructions without any software level locking, which makes it very efficient for concurrent access. " - Erlang :atomics documentation.

Feedback is welcome. :wave:

(I would like to also mention that I’m looking for employment, if you are an employer or your company is hiring I would be happy to talk with you. PM me. Thank you!)

Most Liked

axelson

axelson

Scenic Core Team

Looks like a neat library! Could you do a high-level comparison between Matrax and Matrex (matrex | Hex)? Since the names are so similar I’m going to have a hard time keeping them straight! (and good luck on your job search!)

preciz

preciz OP

The matrix_reloaded library explicitly says that “…if you need make fast operations on matrices, please use Matrex library.”

I have did a few benchmarks ignoring the above warning, and Matrax is faster.
Matrax is still missing a lot of matrix operations found in matrix_reloaded, however if it is this much faster I will implement them in the next days (the ones which makes sense with :atomics).

Keep in mind however that this is not the best benchmark.
One of the benefits of Matrax is concurrency which is not benchmarked here.
(transpose is 14k times faster because Matrax doesn’t move the data, only modifies the access path)

Benchmark suite executing with the following configuration:
warmup: 2 s
time: 5 s
memory time: 0 ns
parallel: 1
inputs: none specified
Estimated total run time: 14 s

Benchmarking matrax_put...
Benchmarking mr_update_element...

Name                        ips        average  deviation         median         99th %
matrax_put              83.02 K      0.0120 ms   ±357.54%     0.00946 ms      0.0177 ms
mr_update_element      0.0858 K       11.65 ms     ±2.96%       11.55 ms       13.08 ms

Comparison: 
matrax_put              83.02 K
mr_update_element      0.0858 K - 967.11x slower +11.64 ms

Benchmarking matrax_get...
Benchmarking mr_get_element...

Name                     ips        average  deviation         median         99th %
matrax_get           74.23 K      0.0135 ms   ±287.15%      0.0113 ms      0.0195 ms
mr_get_element      0.0920 K       10.87 ms     ±2.56%       10.77 ms       11.96 ms

Comparison: 
matrax_get           74.23 K
mr_get_element      0.0920 K - 807.29x slower +10.86 ms

Benchmarking matrax_transpose...
Benchmarking mr_transpose...

Name                       ips        average  deviation         median         99th %
matrax_transpose        6.96 M     0.00014 ms ±23433.64%     0.00005 ms     0.00070 ms
mr_transpose         0.00049 M        2.05 ms     ±6.64%        2.03 ms        2.43 ms

Comparison: 
matrax_transpose        6.96 M
mr_transpose         0.00049 M - 14252.96x slower +2.05 ms
preciz

preciz OP

I love Matrex that is why I gave a similar name :slight_smile:
The A in MatrAx is for :atomics.

MatrEx uses 4 byte floats.
MatrAx uses 64 bit integers and a mutable data structure under the hood called :atomics.

MatrEx optionally(?) depends on native code (NIFs).
MatrAx only requires Elixir.

MatrEx is more feature rich.
MatrAx only implements features that makes sense with :atomics
(at least that is the goal now).

MatraAx and MatrEx serve a different purpose and are not really similar,
apart from the fact that they are matrix libraries.

MatrAx use case example:
Let’s say you have 10x10 board with 25 possible states represented as bitmasks.
You could manipulate the states of the board’s cells from multiple processes concurrently and
only ping the processes that have the reference to update a view based on that.
I’m not sure if I’m clear but I have actually done something like this and :atomics were of course
way faster than lists.

Last Post!

preciz

preciz OP

rewrite matrix_reloaded with Streams instead of Enum

I think that would actually hurt performance or wouldn’t make a huge difference.
Since Matrax is limited to 64 bit integers because of :atomics maybe
a better change would be to support things Matrax can’t because of this limitation.

Where Next? Top

Trending in Announcing Top

woylie
Flop is an Elixir library that applies filtering, ordering and pagination parameters to your Ecto queries. offset-based pagination with...
New
MRdotB
I needed to reuse React components from my Chrome extension in my Phoenix/LiveView backend. I noticed that for Svelte/Vue, there are live...
New
woylie
I released Doggo, a collection of unstyled Phoenix components. https://github.com/woylie/doggo Features Unstyled Phoenix components....
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
anuaralfetahe
Hello Published a new library - ProcessHub! ProcessHub is a library designed to manage process distribution within the Elixir cluster. ...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New
sergio
It’s not that it’s vocabulary is too advanced. It’s something worse. I get lost trying to follow even a paragraph written by Claude. It’...
New
AstonJ
This showed up on my feed.. anyone heard of it? Just hype? Ox Alpha is a reasoning model designed for coding, sustained ag...
New
sorenone
Today we’re releasing Oban for Python. Not an Oban client in Python. Not a pythonx wrapper embedded in Elixir. Nope, it’s a fully operati...
New
akoutmos
@hugobarauna, Dr. Dimitrios Koutmos (my brother) and I (Alex Koutmos) have been hard at work on writing a book on how you can use Elixir ...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews