Некоторые параметры, которые у вас есть для анимации графиков в Jupyter / IPython, с использованием matplotlib:
display
в цикле Используйте IPython.display.display(fig)
для отображения фигуры на выходе. Используя цикл, вы хотите очистить вывод до отображения новой фигуры. Обратите внимание, что эта методика дает в целом не столь гладкие результы. Поэтому я бы посоветовал использовать любое из приведенных ниже. import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
from IPython.display import display, clear_output
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
l, = ax.plot([0,2*np.pi],[-1,1])
animate = lambda i: l.set_data(t[:i], x[:i])
for i in range(len(x)):
animate(i)
clear_output(wait=True)
display(fig)
plt.show()
%matplotlib notebook
Использовать магию IPython %matplotlib notebook
для установки бэкэнд на бэкэнд ноутбука. Это приведет к сохранению фигуры вместо отображения статического файла png и, следовательно, может также отображать анимацию. Полный пример: %matplotlib notebook
import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
l, = ax.plot([0,2*np.pi],[-1,1])
animate = lambda i: l.set_data(t[:i], x[:i])
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=len(t))
plt.show()
%matplotlib tk
Используйте магию IPython %matplotlib tk
, чтобы установить бэкэнд на бэкэнд tk. Это откроет фигуру в новом окне графика, который является интерактивным и может также показывать анимацию. Полный пример: %matplotlib tk
import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
l, = ax.plot([0,2*np.pi],[-1,1])
animate = lambda i: l.set_data(t[:i], x[:i])
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=len(t))
plt.show()
from IPython.display import HTML
HTML(ani.to_html5_video())
или использовать plt.rcParams["animation.html"] = "html5"
в начале ноутбука. Это потребует наличия видеокодеков ffmpeg для конвертирования в видео HTML5. Затем видео отображается в строке. Поэтому он совместим с бэкэндом %matplotlib inline
. Полный пример: %matplotlib inline
import matplotlib.pyplot as plt
plt.rcParams["animation.html"] = "html5"
import matplotlib.animation
import numpy as np
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
l, = ax.plot([0,2*np.pi],[-1,1])
animate = lambda i: l.set_data(t[:i], x[:i])
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=len(t))
ani
%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
l, = ax.plot([0,2*np.pi],[-1,1])
animate = lambda i: l.set_data(t[:i], x[:i])
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=len(t))
from IPython.display import HTML
HTML(ani.to_html5_video())
from IPython.display import HTML
HTML(ani.to_jshtml())
или использование plt.rcParams["animation.html"] = "jshtml"
в начале ноутбука. Это отобразит анимацию как HTML с JavaScript. Это очень совместимо с большинством новых браузеров, а также с бэкэндом %matplotlib inline
. Он доступен в matplotlib 2.1 или выше. Полный пример: %matplotlib inline
import matplotlib.pyplot as plt
plt.rcParams["animation.html"] = "jshtml"
import matplotlib.animation
import numpy as np
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
l, = ax.plot([0,2*np.pi],[-1,1])
animate = lambda i: l.set_data(t[:i], x[:i])
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=len(t))
ani
%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
t = np.linspace(0,2*np.pi)
x = np.sin(t)
fig, ax = plt.subplots()
l, = ax.plot([0,2*np.pi],[-1,1])
animate = lambda i: l.set_data(t[:i], x[:i])
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=len(t))
from IPython.display import HTML
HTML(ani.to_jshtml())
За счет большей памяти можно составить полную таблицу с 256 записями шестнадцатеричных кодов:
static const char _hex2asciiU_value[256][2] =
{ {'0','0'}, {'0','1'}, /* ..., */ {'F','E'},{'F','F'} };
Затем прямой индекс в таблицу, никакой бит, играющий требуемый.
const char *pHexVal = pHex[*pChar];
pszHex[0] = pHexVal[0];
pszHex[1] = pHexVal[1];
Функция, поскольку показано, когда я пишу это, производит неправильный вывод, даже когда _hex2asciiU_value полностью указан. Следующие работы кода, и на моем MacBook Pro на 2.33 ГГц работают приблизительно через 1,9 секунды за 200 000 000 миллионами символов.
#include <iostream>
using namespace std;
static const size_t _h2alen = 256;
static char _hex2asciiU_value[_h2alen][3];
string char_to_hex( const unsigned char* _pArray, unsigned int _len )
{
string str;
str.resize(_len*2);
char* pszHex = &str[0];
const unsigned char* pEnd = _pArray + _len;
const char* pHex = _hex2asciiU_value[0];
for( const unsigned char* pChar = _pArray; pChar != pEnd; pChar++, pszHex += 2 ) {
pszHex[0] = _hex2asciiU_value[*pChar][0];
pszHex[1] = _hex2asciiU_value[*pChar][1];
}
return str;
}
int main() {
for(int i=0; i<_h2alen; i++) {
snprintf(_hex2asciiU_value[i], 3,"%02X", i);
}
size_t len = 200000000;
char* a = new char[len];
string t1;
string t2;
clock_t start;
srand(time(NULL));
for(int i=0; i<len; i++) a[i] = rand()&0xFF;
start = clock();
t1=char_to_hex((const unsigned char*)a, len);
cout << "char_to_hex conversion took ---> " << (clock() - start)/(double)CLOCKS_PER_SEC << " seconds\n";
}
Последовательно добираясь ~4ms на моем Athlon 64 4200 + (~7ms с исходным кодом)
for( const unsigned char* pChar = _pArray; pChar != pEnd; pChar++) {
const char* pchars = _hex2asciiU_value[*pChar];
*pszHex++ = *pchars++;
*pszHex++ = *pchars;
}
Я не уверен выполнение его, больше байтов за один раз будет лучше..., что Вы, вероятно, просто получите тонны неудачных обращений в кэш и значительно замедлите его.
То, что Вы могли бы попробовать, должно развернуть цикл, хотя, сделайте большие шаги и сделайте больше символов каждый раз через цикл, для удаления части цикла наверху.
Удостоверьтесь, что Ваша компиляторная оптимизация включена к самому высокому рабочему уровню.
Вы знаете, флаги как '-O1' к '-03' в gcc.
Я нашел, что использование индекса в массив, а не указателя, может ускорить вещи галочка. Все это зависит от того, как Ваш компилятор принимает решение оптимизировать. Ключ - то, что процессор имеет инструкции сделать сложные вещи как [i*2+1] в единственной инструкции.
Если Вы довольно одержимы скоростью здесь, можно сделать следующее:
Каждый символ составляет один байт, представляя два шестнадцатеричных значения. Таким образом каждый символ является действительно двумя четырехразрядными значениями.
Так, можно сделать следующее:
Таким образом, в единственной инструкции, Вы выполните 16 поиска по таблице в меньшем количестве часов, чем она обычно берет, чтобы сделать всего одну (pshufb, 1 задержка часов на Penryn).
Так, на вычислительных шагах:
Воздействуйте на 32 бита за один раз (4 символа), затем имейте дело с хвостом в случае необходимости. То, когда я сделал это осуществление с URL, кодирующим полный поиск по таблице для каждого символа, было немного быстрее, чем логические конструкции, таким образом, можно хотеть протестировать это в контексте также для принятия кэширующихся проблем.
не собираясь иметь большое значение... *pChar-(ofs*16) может быть, покончили [*pCHar и 0x0F]
Для одного, вместо того, чтобы умножиться 16
сделайте a bitshift << 4
Также не используйте std::string
, вместо этого просто создайте буфер на "куче" и затем delete
это. Это будет более эффективно, чем объектное разрушение, которое необходимо от строки.
Изменение
ofs = *pChar >> 4;
pszHex[0] = pHex[ofs];
pszHex[1] = pHex[*pChar-(ofs*16)];
кому:
int upper = *pChar >> 4;
int lower = *pChar & 0x0f;
pszHex[0] = pHex[upper];
pszHex[1] = pHex[lower];
результаты примерно в 5%-м ускорении.
Запись результата двух байтов во время, как предложено Robert приводит приблизительно к 18%-му ускорению. Код изменяется на:
_result.resize(_len*2);
short* pszHex = (short*) &_result[0];
const unsigned char* pEnd = _pArray + _len;
const char* pHex = _hex2asciiU_value;
for(const unsigned char* pChar = _pArray;
pChar != pEnd;
pChar++, ++pszHex )
{
*pszHex = bytes_to_chars[*pChar];
}
Необходимая инициализация:
short short_table[256];
for (int i = 0; i < 256; ++i)
{
char* pc = (char*) &short_table[i];
pc[0] = _hex2asciiU_value[i >> 4];
pc[1] = _hex2asciiU_value[i & 0x0f];
}
Выполнение его, 2 байта за один раз или 4 байта за один раз, вероятно, приведут к еще большим ускорениям, как указано Allan Wind, но затем это становится более хитрым, когда необходимо иметь дело с нечетными символами.
Если Вы чувствуете себя предприимчивыми, Вы могли бы попытаться адаптировать устройство Вареного пудинга, чтобы сделать это.
Результаты находятся на процессоре Intel Core Duo 2 и gcc -O3
.
Всегда мера, что Вы на самом деле получаете более быстрые результаты — pessimization, симулирующий быть оптимизацией, менее, чем бесполезна.
Всегда тест, что Вы получаете корректные результаты — ошибка, симулирующая быть оптимизацией, совершенно опасен.
И всегда имейте в виду компромисс между скоростью и удобочитаемостью — жизнь слишком коротка, чтобы любой поддержал нечитабельный код.
(Обязательная ссылка на кодирование для жестокого психопата, который знает, где Вы живете.)
Быстрее C Implmentation
Это работает почти 3x быстрее, чем реализация C++. Не уверенный, почему, поскольку это довольно подобно. Для последней реализации C++, что я отправил его, занял 6,8 секунд для пробежки 200 000 000 символьных массивов. Реализация заняла только 2,2 секунды.
#include <stdio.h>
#include <stdlib.h>
char* char_to_hex(const unsigned char* p_array,
unsigned int p_array_len,
char** hex2ascii)
{
unsigned char* str = malloc(p_array_len*2+1);
const unsigned char* p_end = p_array + p_array_len;
size_t pos=0;
const unsigned char* p;
for( p = p_array; p != p_end; p++, pos+=2 ) {
str[pos] = hex2ascii[*p][0];
str[pos+1] = hex2ascii[*p][1];
}
return (char*)str;
}
int main()
{
size_t hex2ascii_len = 256;
char** hex2ascii;
int i;
hex2ascii = malloc(hex2ascii_len*sizeof(char*));
for(i=0; i<hex2ascii_len; i++) {
hex2ascii[i] = malloc(3*sizeof(char));
snprintf(hex2ascii[i], 3,"%02X", i);
}
size_t len = 8;
const unsigned char a[] = "DO NOT WANT";
printf("%s\n", char_to_hex((const unsigned char*)a, len, (char**)hex2ascii));
}
Эта функция блока (базирующийся от моего предыдущего сообщения здесь, но я должен был изменить понятие немного для получения, это для фактической работы) обрабатывает 3,3 миллиарда вводимых символов в секунду (6,6 миллиардов выходных символов) на одном ядре Core 2 Конроу 3 ГГц. Penryn, вероятно, быстрее.
%include "x86inc.asm"
SECTION_RODATA
pb_f0: times 16 db 0xf0
pb_0f: times 16 db 0x0f
pb_hex: db 48,49,50,51,52,53,54,55,56,57,65,66,67,68,69,70
SECTION .text
; int convert_string_to_hex( char *input, char *output, int len )
cglobal _convert_string_to_hex,3,3
movdqa xmm6, [pb_f0 GLOBAL]
movdqa xmm7, [pb_0f GLOBAL]
.loop:
movdqa xmm5, [pb_hex GLOBAL]
movdqa xmm4, [pb_hex GLOBAL]
movq xmm0, [r0+r2-8]
movq xmm2, [r0+r2-16]
movq xmm1, xmm0
movq xmm3, xmm2
pand xmm0, xmm6 ;high bits
pand xmm2, xmm6
psrlq xmm0, 4
psrlq xmm2, 4
pand xmm1, xmm7 ;low bits
pand xmm3, xmm7
punpcklbw xmm0, xmm1
punpcklbw xmm2, xmm3
pshufb xmm4, xmm0
pshufb xmm5, xmm2
movdqa [r1+r2*2-16], xmm4
movdqa [r1+r2*2-32], xmm5
sub r2, 16
jg .loop
REP_RET
Обратите внимание, что это использует x264 синтаксис блока, который делает это более портативным (к 32-разрядному по сравнению с 64-разрядным, и т.д.). Преобразовать это в синтаксис по Вашему выбору тривиально: r0, r1, r2 являются этими тремя аргументами функциям в регистрах. Это немного похоже на псевдокод. Или можно просто получить common/x86/x86inc.asm от x264 дерева и включать это для выполнения его исходно.
P.S. Переполнение стека, я неправильно для того, чтобы напрасно тратить время на такой тривиальной вещи? Или действительно ли это является потрясающим?
Это - моя версия, которая, в отличие от версии OP, не принимает это std::basic_string
имеет его данные в непрерывном регионе:
#include <string>
using std::string;
static char const* digits("0123456789ABCDEF");
string
tohex(string const& data)
{
string result(data.size() * 2, 0);
string::iterator ptr(result.begin());
for (string::const_iterator cur(data.begin()), end(data.end()); cur != end; ++cur) {
unsigned char c(*cur);
*ptr++ = digits[c >> 4];
*ptr++ = digits[c & 15];
}
return result;
}