Для человека без comp-sci фона, что такое лямбда в мире компьютерных наук?
Я проиллюстрирую его интуитивно шаг за шагом в простой и понятной форме python.
Короче говоря, лямбда - это просто анонимная и встроенная функция.
Давайте начнем с назначения, чтобы понять
lambdas
как первокурсник с фоном базовой арифметики.Схема присвоения - это «имя = значение», см.:
In [1]: x = 1 ...: y = 'value' In [2]: x Out[2]: 1 In [3]: y Out[3]: 'value'
«x», «y» - это имена и 1, «значение» - значения. Попробуйте функцию в математике
In [4]: m = n**2 + 2*n + 1 NameError: name 'n' is not defined
Отчеты об ошибках, вы не можете написать математику непосредственно в качестве кода, «n» должно быть определено или присвоено значению.
In [8]: n = 3.14 In [9]: m = n**2 + 2*n + 1 In [10]: m Out[10]: 17.1396
Теперь он работает, что если вы настаиваете на объединении двух линий seperarte с одним. Наступает
lambda
In [13]: j = lambda i: i**2 + 2*i + 1 In [14]: j Out[14]:
> Не сообщалось об ошибках.
Это взгляд на
lambda
, он позволяет вам написать функцию в одной строке, как вы это делаете в математически в компьютер.Мы увидим это позже.
Давайте продолжим углубляться в «присвоение».
Как показано выше, символ равенства
=
работает для простых данных (1 и «значение») и простого выражения (n ** 2 + 2 * n + 1).Попробуйте следующее:
In [15]: x = print('This is a x') This is a x In [16]: x In [17]: x = input('Enter a x: ') Enter a x: x
Он работает для простых операторов, в python 7 имеется 11 типов. Простые инструкции - Документация Python 3.6.3
Как насчет составной инструкции,
In [18]: m = n**2 + 2*n + 1 if n > 0 SyntaxError: invalid syntax #or In [19]: m = n**2 + 2*n + 1, if n > 0 SyntaxError: invalid syntax
Наступает
def
включить ее работуIn [23]: def m(n): ...: if n > 0: ...: return n**2 + 2*n + 1 ...: In [24]: m(2) Out[24]: 9
Tada, проанализируйте его, 'm' - это имя, 'n ** 2 + 2 * n + 1' является значением.
:
является вариантом '='.Теперь вернемся к
lambda
, у нас есть функция с именем «m»Попробуйте:
g23]
In [28]: m = m(3) In [29]: m Out[29]: 16
Здесь есть два имени «m», функция
m
уже имеет имя, дублируется.Это форматирование:
In [27]: m = def m(n): ...: if n > 0: ...: return n**2 + 2*n + 1 SyntaxError: invalid syntax
Это не умная стратегия, поэтому отчеты об ошибках
Мы должны удалить одну из них, установить функцию без имени.
m = lambda n:n**2 + 2*n + 1
Это называется «анонимная функция»
В заключение,
lambda
в встроенной функции, которая позволяет вам написать функцию в одной прямой так же, как в математикеlambda
, АнонимНадеюсь, это поможет.
Вы можете улучшить конвейер (если вы кодируете на C, компилятор сделает это за вас) и использовать интервал задержки инструкции bne
. Это улучшит ваш параллелизм на уровне команд .
Предполагая, что у вас есть что-то вроде процессора Mips с 1 слотом задержки и 5-ступенчатым конвейером (извлечение инструкций, декодирование, выполнение, память, обратная запись).
Этот конвейер вводит Read After Write Опасности, связанные с зависимостью от данных, больше всего были в $3
регистре.
Атака RaW приводит к остановке вашего трубопровода.
# Reverse the order of data in Reference and store it in $02
Loop: and $03, $01, $06 # mask out one piece ($03 = Reference & $06)
addi $04, $04, -1 # decrement Loop counter (RaW on $3)
sllv $03, $03, $05 # shift piece to new position ($03 <<= $05)
sllv $06, $06, $05 # shift mask for next piece
or $02, $02, $03 # put piece into $02 ($02 |= $03)
and $03, $01, $06 # mask out next piece (#03 = Reference & $06)
srlv $06, $06, $05 # shift mask back
srlv $03, $03, $05 # shift piece to new position ($03 >>= $05)
addi $05, $05, -4 # decrease shift amount by 4
or $02, $02, $03 # put new piece into $02 ($02 |= $03)
bne $04, [110], Loop # keep looping while $04 != 0
sll $06, $06, 2 # shift mask for next loop
Если у вас суперскалярный процессор, решение нуждается в некоторых изменениях.
Чтобы изменить ваши биты, вы можете использовать следующий код.
static int rev(int v){
// swap adjacent pairs of bits
v = ((v >> 2) & 0x3333) | ((v & 0x3333) << 2);
// swap nibbles
v = ((v >> 4) & 0x0f0f) | ((v & 0x0f0f) << 4);
// swap bytes
v = ((v >> 8) & 0x00ff) | ((v & 0x00ff) << 8);
return v;
}
Реализация MIPS состоит из 15 инструкций.
rev: # value to reverse in $01
# uses $02 reg
srli $02, $01, 2
andi $02, $02, 0x3333
andi $01, $01, 0x3333
slli $01, $01, 2
or $01, $01, $02
srli $02, $01, 4
andi $02, $02, 0x0f0f
andi $01, $01, 0x0f0f
slli $01, $01, 4
or $01, $01, $02
srli $02, $01, 8
andi $02, $02, 0xff
andi $01, $01, 0xff
slli $01, $01, 8
or $01, $01, $02
# result in $01
Обратите внимание, что вы можете одновременно обратить 2x16 бит, просто удвоив константы (и даже 4 на 64-битных машинах). Но я не уверен, что это полезно в вашем случае.
Для очень простого и эффективного подхода используйте 256-байтовую таблицу поиска и выполните 2 поиска:
extern unsigned char const xtable[256];
unsigned int ref = 4149;
unsigned int rev = (xtable[ref & 0xFF] << 8) | xtable[ref >> 8];
Массив xtable
можно статически инициализировать с помощью набора макросов:
#define S(x) ((((x) & 0x0003) << 14) | (((x) & 0x000C) << 10) | \
(((x) & 0x0030) << 6) | (((x) & 0x00C0) << 2) | \
(((x) & 0xC000) >> 14) | (((x) & 0x3000) >> 10) | \
(((x) & 0x0C00) >> 6) | (((x) & 0x0300) >> 2))
#define X8(m,n) m((n)+0), m((n)+1), m((n)+2), m((n)+3), \
m((n)+4), m((n)+5), m((n)+6), m((n)+7)
#define X32(m,n) X8(m,(n)), X8(m,(n)+8), X8(m,(n)+16), X8(m,(n)+24)
unsigned char const xtable[256] = {
X32(S, 0), X32(S, 32), X32(S, 64), X32(S, 96),
X32(S, 128), X32(S, 160), X32(S, 192), X32(S, 224),
};
#undef S
#undef X8
#undef X32
Если пространство не дорого, вы можете использовать один просмотр таблицы размером 128 КБ, которую вы будете вычислять во время запуска или генерировать с помощью скрипта и включать во время компиляции, но это несколько расточительно и не очень кэш удобно.