LINUX.ORG.RU

Избранные сообщения unC0Rr

FreeBSD, «объединить» аудиоустройства

Форум — General

Имеется два (на самом деле четыре, но остальные два — digital output, они к делу не относятся) pcm — 0 (play/rec) и 1 (rec).

Встроенный микрофон находится на pcm1 (dsp1.0), внешний (через 1/8 (3.5) Jack) — pcm0 (dsp0.0). Хочется сделать запись по дефолту с dsp1.0, сохранив output на dsp0.0 и со встроенных спикеров, и через 1/8 (3.5) Jack и переключать запись на dsp0.0 при втыкании микрофона в 1/8 (3.5) Jack.

Пытался шаманить device.hints, но я не совсем понимаю как оно устроено, потому либо пропадает output, либо пропадает возможность записывать в input.

Устанавливать sndio/oss/virtual_oss/pulseaudio/alsa/whatever не предлагать.

@iZEN (кастую потому что не подписан на тег freebsd).

Решение.

 ,

mord0d
()

std::bind vs lambda

Форум — Development

Есть метод, который принимает callback:

void Bar::setCallback(const std::function<void(int, int)> &cb) {}

Я туда хочу передать метод класса, соответственно есть два пути:

// Метод, который передаём
void Foo::callback(int a, int b) {}

// Путь первый
bar->setCallback(std::bind(&Foo::callback, this, std::placeholders::_1, std::placeholders::_2));

// Путь второй
bar->setCallback([this] (int a, int b) { callback(a, b); });

Какой путь лучше, если рассмотреть с разных точек зрения: удобство написания, читаемость, может быть быстродействие и размер, если критично? Ваше личное мнение.

 , ,

ox55ff
()

Релиз FreeBSD 12.0

Новости — BSD
Группа BSD

Сегодня состоялся новый крупный релиз свободной операционной системы FreeBSD. Новый релиз был сфокусирован на поддержку современных графических адаптеров, много внимания было уделено системе шифрования дисков GELI и системе контейнерной виртуализации VIMAGE. Здесь будут рассмотрены на мой взгляд самые значимые из изменений.

( читать дальше... )

>>> Подробности

 

Unicode4all
()

Новые камни Intel, 4/8 - всё

Форум — Talks
Intel Core i7-8700K: 6 ядер/12 потоков, 3,7/4,7 ГГц, 12 МБ кэша L3, $380;
Intel Core i7-8700: 6 ядер/12 потоков, 3,2/4,6 ГГц, 12 МБ кэша L3, $320;
Intel Core i5-8600K: 6 ядер/6 потоков, 3,6/4,3 ГГц, 9 МБ кэша L3, $265;
Intel Core i5-8400: 6 ядер/6 потоков, 2,8/4 ГГц, 9 МБ кэша L3, $190;
Intel Core i3-8350K: 4 ядра/4 потока, 4 ГГц, 8 МБ кэша L3, $180;
Intel Core i3-8100: 4 ядра/4 потока, 3,6 ГГц, 6 МБ кэша L3, $120.

Продажи начинаются 16 сентября

 ,

Deleted
()

Установить Qt 5.5.1 в freebsd 10.2

Форум — Development

Всем здрасьте.

Собственно вопрос к БСД-шникам.

Имею удивительную ситуацию: установил на виртуалку FreeBSD 10.2, обновил все порты (через portsnap) и делал pkg upgrade/update.

Но при попытке установить «свежее» Qt 5.5.1:

sudo pkg install qt5-core

оно мне предлагает, елки, протухшее Qt 5.4.x, хотя в портах я вижу что там конфиги для Qt 5.5.1...

Что за п#@ц? Фишка еще в том, что в предыдущем 10.1 релизе этой г@#й фряхи устанавливается Qt 5.5.1...

Компилить самому Qt из портов нет желания... Может кто просветит меня, о, светлоликие, в чем хрень?

 ,

kuzulis
()

IDE для Haskell

Форум — Desktop

Имеется ли какая-нибудь IDE для программирования на Haskell в Ubuntu?

Или так и придётся сидеть в консольке?

Перемещено Pinkbyte из development

 ,

zamazan4ik
()

Научите правильно готовить монады через CPS

Форум — Development

Тут будет много букв, я морально готовился месяц, поэтому за объем заранее извиняйте. Сразу скажу - на ассемблерах я не писатель, и цель треда - не обсуждение дизайнерских решений, а производительность монад. Суть всплывёт ближе к концу (я надеюсь).

Представим, что мы моделируем некий процессор, у которого есть простой набор инструкций. С инструкций и начнем:

data Register = R1 | R2 | R3 | R4 | R5 | R6
                deriving (Show)
     
data Operator = ADD | SUB | MUL | DIV
              | LESS | EQUAL | AND | OR | NOT
              | MOV
              | JMT | JMF | JMP
              | PRN | NOP
                deriving (Show)

class OperandClass a where
   toOperand :: a -> Operand

instance OperandClass Register where
   toOperand = R

instance OperandClass Operand where
   toOperand = id

instance OperandClass () where
   toOperand _ = N

data Operand = R !Register | V !Double | I !Int | N
               deriving (Show)

type Instruction = (Operator, Operand, Operand) 

Иными словами, всё очень просто: инструкция - это кортеж оператора и операндов, операндом могут быть регистр, значение, или ничего.

Чтобы кодить на нашем псевдоассемблере, потребуется таки простенький компилятор. Цель его - записать все инструкции в списочек.

-- | Monad for programming instructions 

type ASM a = State [Instruction] a

compile :: ASM a -> [Instruction]
compile c = execState c []

op :: (OperandClass s, OperandClass d) => Operator -> s -> d -> ASM ()
op cmd src dst = modify $ \s -> s ++ [(cmd, toOperand src, toOperand dst)]

pos :: ASM Int
pos = liftM length get

nop :: ASM Int
nop = do { p <- pos; op NOP () (); return p}

putOp :: (OperandClass s, OperandClass d) => Int -> Operator -> s -> d -> ASM ()
putOp p cmd src dst = do
    let instr = (cmd, toOperand src, toOperand dst)
    (before,after) <- liftM (splitAt p) get 
    put $ before ++ instr : tail after

Тут, опять же, ничего сложного. Для наглядности, немного забегая вперед, приведу пример кода на этом «ассемблере». Данный код считает квадратный корень заданного числа методом Герона с заданным приближением (числом шагов):

-- | Heron's method to calculate square root
-- Inputs:  r1 - value to calculate square root from
--          r2 - number of iterations
-- Outputs: r6 - output value
heron :: ASM ()
heron = do
   op MOV (V 1) R5
   op MOV (V 0) R3
   iterStart <- pos
   op MOV R3 R4
   op EQUAL R2 R4
   ifFalse <- nop
   op MOV R1 R6
   op DIV R5 R6
   op ADD R5 R6
   op MUL (V 0.5) R6
   op MOV R6 R5
   op ADD (V 1) R3
   op JMP (I iterStart) ()
   loopEnd <- pos
   putOp ifFalse JMT R4 (I loopEnd)
   op PRN R6 ()

Надеюсь, тут становится ясна необходимость в действиях pos, nop, и putOp, описанных ранее - их суть в расстановке меток и замене пустышек на инструкции, привязанные к меткам. Не самое элегантное, но, как по мне, вполне решение для организации циклических конструкций.

Идём дальше. Чтобы это всё выполнять, нужна ещё одна монада:

-- | Monad for executing instructions

data Registers = Registers
               { r1 :: !Double
               , r2 :: !Double
               , r3 :: !Double
               , r4 :: !Double
               , r5 :: !Double
               , r6 :: !Double
               } deriving (Show)

initialRs :: Registers
{-# INLINE initialRs #-}
initialRs = Registers
            { r1 = 0
            , r2 = 0
            , r3 = 0
            , r4 = 0
            , r5 = 0
            , r6 = 0
            }

type CPU a = StateT Registers IO a

execute ::Registers -> [Instruction] -> IO Registers
execute rs code = execStateT (exec code) rs
  where
   {-# INLINE exec #-}
   exec ((JMP, I pos, _    ):is) = {-# SCC "JMP" #-} exec $! drop pos code
   exec ((JMF,   reg, I pos):is) = {-# SCC "JMF" #-} readVal reg >>= \v ->
                                                     exec $! if toBool v
                                                             then is
                                                             else drop pos code
   exec ((JMT,   reg, I pos):is) = {-# SCC "JMT" #-} readVal reg >>= \v ->
                                                     exec $! if toBool v
                                                             then drop pos code
                                                             else is
   exec ((ins,   src,   dst):is) = {-# SCC "OP"  #-} execOP ins src dst >> exec is
   exec []                       = return ()

execOP :: Operator -> Operand -> Operand -> CPU ()
{-# INLINE execOP #-}
execOP ADD   src dst = {-# SCC "ADD"   #-} arith ADD   src dst
execOP SUB   src dst = {-# SCC "SUB"   #-} arith SUB   src dst
execOP MUL   src dst = {-# SCC "MUL"   #-} arith MUL   src dst
execOP DIV   src dst = {-# SCC "DIV"   #-} arith DIV   src dst
execOP LESS  src dst = {-# SCC "LESS"  #-} logic LESS  src dst
execOP EQUAL src dst = {-# SCC "EQUAL" #-} logic EQUAL src dst
execOP AND   src dst = {-# SCC "AND"   #-} logic AND   src dst
execOP OR    src dst = {-# SCC "OR"    #-} logic OR    src dst
execOP NOT   src dst = {-# SCC "NOT"   #-} logic NOT   src dst
execOP MOV   src dst = {-# SCC "MOV"   #-} readVal src >>= \v -> putVal dst $! v
execOP PRN   src _   = {-# SCC "PRN"   #-} readVal src >>= \v -> liftIO $ print v 

arith :: Operator -> Operand -> Operand -> CPU ()
{-# INLINE arith #-}
arith op src dst = do
    v1 <- readVal src
    v2 <- readVal dst
    case op of
       ADD -> putVal dst $! v2 + v1
       SUB -> putVal dst $! v2 - v1
       MUL -> putVal dst $! v2 * v1
       DIV -> putVal dst $! v2 / v1

logic :: Operator -> Operand -> Operand -> CPU ()
{-# INLINE logic #-}
logic op src dst = do
     v1 <- readVal src
     v2 <- readVal dst
     case op of
        LESS  -> putVal dst $! fromBool $ v2 <  v1
        EQUAL -> putVal dst $! fromBool $ v2 == v1
        AND   -> putVal dst $! fromBool $ toBool v1 && toBool v2
        OR    -> putVal dst $! fromBool $ toBool v1 && toBool v2
        NOT   -> putVal dst $! fromBool . not . toBool $ v1

fromBool :: Bool -> Double
{-# INLINE fromBool #-}
fromBool True  = 1
fromBool False = 0

toBool :: Double -> Bool
{-# INLINE toBool #-}
toBool 0 = False
toBool _ = True

readVal :: Operand -> CPU Double
{-# INLINE readVal #-}
readVal (R R1) = gets r1
readVal (R R2) = gets r2
readVal (R R3) = gets r3
readVal (R R4) = gets r4
readVal (R R5) = gets r5
readVal (R R6) = gets r6
readVal (V v)  = return v

putVal :: Operand -> Double -> CPU ()
{-# INLINE putVal #-}
putVal (R R1) v = modify $ \s -> s { r1 = v }
putVal (R R2) v = modify $ \s -> s { r2 = v }
putVal (R R3) v = modify $ \s -> s { r3 = v }
putVal (R R4) v = modify $ \s -> s { r4 = v }
putVal (R R5) v = modify $ \s -> s { r5 = v }
putVal (R R6) v = modify $ \s -> s { r6 = v }

Тут кода уже побольше, но, опять же, ничего сложного - мы просто проходимся по списку инструкций и интерпретируем каждую, выполняя соответствующие действия. Состояние нашего игрушечного процессора - шесть дабловых регистров.

Вот и всё!

Полная версия кода доступна на Гитхабе.

С файликом, загруженным в ghci, можно поиграться, например, так:

let h = compile heron
execute (initialRs {r1 = 25, r2 = 4}) h

5.015247601944898 Registers {r1 = 25.0, r2 = 4.0, r3 = 4.0, r4 = 1.0, r5 = 5.015247601944898, r6 = 5.015247601944898}

Но самое важное для меня в данной ситуации - это время, за которое наш компьютер посчитает 10 000 корней. Входные данные и скрипт для запуска есть в репозитории:

$ ghc --make -O3 Asm.hs
$ ./measure.sh

Судя по результатам профайлера, основное время мы таки проводим в нашем процессоре:

COST CENTRE MODULE    %time %alloc

OP          Main       33.6   34.2
PRN         Main       21.4   23.0
READ        Main       16.4   12.8
MOV         Main        8.8   13.2
ADD         Main        5.4    6.7
DIV         Main        3.3    3.7
EQUAL       Main        3.1    3.4
MUL         Main        2.7    3.0
JMT         Main        2.3    0.0
JMP         Main        1.9    0.0


                                                                  individual     inherited
COST CENTRE  MODULE                             no.     entries  %time %alloc   %time %alloc

MAIN         MAIN                                52           0    0.7    0.0   100.0  100.0
 JMT         Main                               113      200000    2.3    0.0    80.7   85.4
  OP         Main                               114     1610000   32.8   33.3    78.3   85.4
   PRN       Main                               121       10000   21.4   23.0    21.4   23.0
   EQUAL     Main                               120      200000    2.7    3.2     2.7    3.2
   JMP       Main                               119      200000    1.9    0.0     1.9    0.0
   MUL       Main                               118      200000    2.7    3.0     2.7    3.0
   ADD       Main                               117      400000    5.4    6.7     5.4    6.7
   DIV       Main                               116      200000    3.3    3.7     3.3    3.7
   MOV       Main                               115      600000    8.2   12.6     8.2   12.6
 EQUAL       Main                               111           0    0.4    0.2     0.4    0.2
 MOV         Main                               108           0    0.6    0.6     0.6    0.6
 OP          Main                               106       40000    0.8    0.9     0.8    0.9
  JMT        Main                               112       10000    0.0    0.0     0.0    0.0
  EQUAL      Main                               110       10000    0.0    0.0     0.0    0.0
  MOV        Main                               107       30000    0.0    0.0     0.0    0.0
 ITER        Main                               105       10000    0.4    0.1     0.4    0.1
 READ        Main                               104           1   16.4   12.8    16.4   12.8
 CAF         Main                               103           0    0.0    0.0     0.0    0.0
  READ       Main                               109           0    0.0    0.0     0.0    0.0

Т.о., исполнение собственно операций (кроме ввода-вывода) занимает около 70% всего времени.

Внимание, суть!. Интересно, как зависит время выполнения от способа организации (или, если хотите, реализации) главной монады в тесте - CPU. Самое простое для начала - попробовать готовые реализации.

Мои результаты:

  • 0.37с - для монады CPU, реализованной поверх пакета transformers
  • 0.39c - для mtl
  • 0.42c - для contstuff

ХаскельВики рекомендует путь джедаев - ручной анроллинг стэков трансформеров и(ли) переход на CPS. Переход на CPS - вообще вещь легендарная, в иных историях успеха оно ускоряет код раз так в 4-8. Проверим:

newtype CPU a = CPU { runCPU :: forall r. Registers -> (a -> Registers -> IO r) -> IO r }

instance Monad CPU where
   return = retCPU
   (>>=)  = bindCPU

instance MonadIO CPU where
   liftIO = lioCPU

retCPU :: a -> CPU a
{-# INLINE retCPU #-}
retCPU x = CPU $ \s k -> k x s

bindCPU :: CPU a -> (a -> CPU b) -> CPU b
{-# INLINE bindCPU #-}
bindCPU (CPU m) f = CPU $ \s0 k -> m s0 $ \a s1 -> runCPU (f a) s1 k

lioCPU :: IO a -> CPU a
{-# INLINE lioCPU #-}
lioCPU f = CPU $ \s k -> f >>= \x -> k x s

get :: CPU Registers
{-# INLINE get #-}
get = CPU $ \s k -> k s s

gets :: (Registers -> a) -> CPU a
{-# INLINE gets #-}
gets f = get >>= \s -> return $! f s

put :: Registers -> CPU ()
{-# INLINE put #-}
put s = CPU $ \_ k -> k () s

modify :: (Registers -> Registers) -> CPU ()
{-# INLINE modify #-}
modify f = get >>= \s -> let s' = f s in put $! s'

Хотите верьте, хотите нет - такой вариант показал результат в 0.41c. Я в печали.

При ручном анроллинге (без CPS):

newtype CPU a = CPU { runCPU :: Registers -> IO (Registers, a) }

instance Monad CPU where
   return = retCPU
   (>>=)  = bindCPU

instance MonadIO CPU where
   liftIO f = CPU $ \s -> f >>= \x -> return (s, x)

retCPU :: a -> CPU a
{-# INLINE retCPU #-}
retCPU x = CPU $ \s -> return (s, x)

bindCPU :: CPU a -> (a -> CPU b) -> CPU b
{-# INLINE bindCPU #-}
bindCPU m f = CPU $ \s -> do (s', a) <- runCPU m s
                             runCPU (f a) s'

get :: CPU Registers
{-# INLINE get #-}
get = CPU $ \s -> return $! (s, s)

gets :: (Registers -> a) -> CPU a
{-# INLINE gets #-}
gets f = get >>= \s -> return $! f s

put :: Registers -> CPU ()
{-# INLINE put #-}
put s = CPU $ \_ -> return (s, ())

modify :: (Registers -> Registers) -> CPU ()
{-# INLINE modify #-}
modify f = get >>= \s -> let s' = f s in put $! s'

...всё несколько лучше, удалось получить 0.34с, но это всё равно не тот прирост, который я ожидал.

Данные эксперименты и опыт коллег, которые-делали-почти-то-же-самое-и-у-них-получилось, наталкивают на мысли, что что-то где-то пошло не так. Поэтому мой вопрос светлейшим умам форума сего - как воспроизвести те впечатляющие результаты с анроллингом и CPS? Какую деталь я мог упустить?

Для вашего удобства, весь код в его текущем состоянии выложен на Гитхабе, каждый вариант в своей ветке.

Простите ещё раз за такую простыню и неровный почерк. Всем любви!

 ,

yoghurt
()

Серверное приложение на Haskell: что происходит с памятью.

Форум — Development

Здравствуйте.

Есть сервер, который на скорости в 10 qps (в будущем может и поболее) обрабатывает короткие запросы. В самом начале он кушает 8032 КБ по показаниям RSS, через сутки или даже поболее — 15980 КБ.

Является ли подобное поведение свидетельством утечки или это норма для GC и программ на Haskell?

 

HolyBoy
()

Я познаю мир

Форум — Science & Engineering

В этом треде мы помогаем лоровцам получше понять и разобраться во всяких интересных математических концепциях. Кто-то до сих пор не понимает почему на ноль делить таки нельзя; кому-то нравятся аналогии «на пальцах» вида детерминант — ориентированный объём, ковектор — (n-1)-мерная плоскость; кому-то будет интересно узнать, что из алгебраической топологии, интеграл это всего-навсего произведение цепи на коцепь. А кто-то до сих пор не знает что такое тензор; возможно, не всем известно, что механику, электродинамику, теорию относительности и квантовую теорию поля можно локально вывести из наикрасивейшего лагранжева формализма; зачем нужны алгебры Ли; что такое ковариантная производная; в чём отличии гомологий от гомотопий, ну и так далее.

Заметьте, это не тред ответов на вопросы вида «почему небо голубое» — за этим идите в гугл; это не тред выполнения за вас домашних заданий — решайте сами; это не тред споров с фриками — игнорируйте их; это тред добра и просвещения. Однако в идеале вы уже должны иметь представление о математике и физике хотя бы на уровне первого-второго курса. Здесь так же можно просить и рекомендовать литературу, можно посылать в английскую википедию, можно и нужно объяснять как можно проще и доступнее (пускай и совсем неформально). Главное, чтобы у зашедшего лоровца появился интерес и желание учиться.

 , ,

mix_mix
()

Аналоги монад Haskell

Форум — Development

1. Какие есть аналоги монад Haskell?
2. Что почитать не слишком заумное (но философское) по монадам на русском? Теорию категорий мне не осилить, я это понял ещё в универе, 15 лет назад.

 

pacify
()

Налетай, DHT

Форум — Talks

Пару месяцев назад вылез из криокамеры и открыл для себя сайт http://btdigg.org/search?info_hash=&q=linux Сразу снес полтерабайта всякой фигни, хранящейся на компе. Линукс тут при том, что в соседнем треде кто-то спрашивал, что сделать с локальной файлопомойкой в линуксе.

Для Ъ: По ссылке сайт, индексирующий все файлы, раздаваемые по DTH через битторент. То есть поиск по эксабайтам информации.

 ,

Rosko
()

#mh и быстрый переезд ящиков

Форум — Desktop

Сейчас директории почтовых указаны на основе некой #mh, которая на данный момент равна ~. Как можно, вручную mv почтовых ящиков в ~/Mail например, указать, что #mh == ~/Mail?

 

ados
()