Самый быстрый способ сохранить массив NumPy в Redis - PullRequest
4 голосов
/ 23 марта 2019

Я использую redis в проекте AI.

Идея состоит в том, чтобы иметь несколько симуляторов среды, в которых выполняются политики на множестве ядер процессора.Симуляторы записывают опыт (список кортежей состояния / действия / награды) на сервер redis (буфер воспроизведения).Затем учебный процесс считывает опыт как набор данных для создания новой политики.Новая политика развернута на симуляторах, данные из предыдущего запуска удалены, и процесс продолжается.

Большая часть опыта захвачена в «состоянии».Который обычно представлен в виде большого массива измерений, скажем, 80 x 80. Симуляторы генерируют их так быстро, как позволяет процессор.

С этой целью у кого-нибудь есть хорошие идеи или опыт лучших /Самый быстрый / простой способ написать много редких массивов в Redis.Это все на одной машине, но позже может быть на множестве облачных серверов.Примеры кода приветствуются!

1 Ответ

6 голосов
/ 23 марта 2019

Не знаю, работает ли он быстрее, но вы можете попробовать что-то вроде этого ...

Сохранение массива Numpy в Redis выглядит следующим образом - см. Функцию toRedis():

  • получить форму массива Numpy и кодировать
  • добавить массив Numpy в виде байтов к форме
  • сохранить закодированный массив под предоставленным ключом

ПолучениеМассив Numpy выглядит следующим образом - см. Функцию fromRedis():

  • извлечение из Redis кодированной строки, соответствующей предоставленному ключу
  • , извлечение формы массива Numpy из строки
  • извлечение данных и повторное заполнение массива Numpy, изменение его формы до первоначальной

#!/usr/bin/env python3

import struct
import redis
import numpy as np

def toRedis(r,a,n):
   """Store given Numpy array 'a' in Redis under key 'n'"""
   h, w = a.shape
   shape = struct.pack('>II',h,w)
   encoded = shape + a.tobytes()

   # Store encoded data in Redis
   r.set(n,encoded)
   return

def fromRedis(r,n):
   """Retrieve Numpy array from Redis key 'n'"""
   encoded = r.get(n)
   h, w = struct.unpack('>II',encoded[:8])
   a = np.frombuffer(encoded, dtype=np.uint16, offset=8).reshape(h,w)
   return a

# Create 80x80 numpy array to store
a0 = np.arange(6400,dtype=np.uint16).reshape(80,80) 

# Redis connection
r = redis.Redis(host='localhost', port=6379, db=0)

# Store array a0 in Redis under name 'a0array'
toRedis(r,a0,'a0array')

# Retrieve from Redis
a1 = fromRedis(r,'a0array')

np.testing.assert_array_equal(a0,a1)

Вы можете повысить гибкость, кодируя dtype массива Numpy вместе с формой.Я этого не делал, потому что, возможно, вы уже знаете, что все ваши массивы относятся к одному конкретному типу, и тогда код будет просто больше и труднее читать без всякой причины.

Грубыйтест на современном iMac :

80x80 Numpy array of np.uint16   => 58 microseconds to write
200x200 Numpy array of np.uint16 => 88 microseconds to write

Ключевые слова : Python, Numpy, Redis, массив, сериализация, сериализация, ключ, incr, уникальный

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...