Forwarded from AI Media The Best
This media is not supported in your browser
VIEW IN TELEGRAM
Советский сериал "Шерлок Холмс" с помощью ИИ Merlin Clone озвучили на разных языках.
Оцените интонации и тембры, мало отличимые от оригинальных голосов актеров.
Лучшие продукты в мире AI — подписаться
Оцените интонации и тембры, мало отличимые от оригинальных голосов актеров.
Лучшие продукты в мире AI — подписаться
🔥13
Forwarded from Мемный Болт Генона
Southwest Airlines, the fourth largest airline in the US, is seemingly unaffected by the problematic CrowdStrike update that caused millions of computers to BSoD (Blue Screen of Death) because it used Windows 3.1. The CrowdStrike issue disrupted operations globally after a faulty update caused newer computers to freeze and stop working, with many prominent institutions, including airports and almost all US airlines, including United, Delta, and American Airlines, needing to stop flights.
Windows 3.1 saves the day during CrowdStrike outage — Southwest Airlines scrapes by with archaic OS
https://www.tomshardware.com/software/windows/windows-31-saves-the-day-during-crowdstrike-outage
🔥19😁8
#video
Существует ли особый "гейский голос"? TL;DR: судя по всему, да, и от языка это не зависит.
youtube.com/watch?v=SF7KCsvcw2g
Существует ли особый "гейский голос"? TL;DR: судя по всему, да, и от языка это не зависит.
youtube.com/watch?v=SF7KCsvcw2g
YouTube
Why do gay people sound like that?
Is GAY FACE real? https://youtu.be/n6JJyrX1u44?si=NAxazRhjR2LcQewI
There is a lot of new research on the 'gay accent' or 'gay voice' - and why it might be that gay men and gay women speak differently than hetero people
Written by: Gregory Brown & Mitchell…
There is a lot of new research on the 'gay accent' or 'gay voice' - and why it might be that gay men and gay women speak differently than hetero people
Written by: Gregory Brown & Mitchell…
🤯8
/g/‘s Tech Memes
Photo
Это, конечно, очень удобно, когда одна и та же библиотека называется по разному в зависимости от дистрибутива.
Или когда название пакета вообще не отражает включаемые либы (привет, build-essential).
Или когда название пакета вообще не отражает включаемые либы (привет, build-essential).
😁13🤡2😭1
Мне бабушка говорила, что если я буду сидеть напротив угла стола, то у меня не будет девушки.
А про парней она ничего не говорила.
А про парней она ничего не говорила.
😁33🥴5🤡3💩2❤1
#prog #rust #rustlib #menacingopensource
Quickly prototype procedural macros using JavaScript or TypeScript!
crates.io/crates/js-macros
Quickly prototype procedural macros using JavaScript or TypeScript!
crates.io/crates/js-macros
👍5
Помнится, в первые дни после переезда я задавался вопросом, как армяне — местные — переносят жару: по идее, более привычные.
Оказалось, никак не переносят — точно так же сидят по домам с кондиционерами
Оказалось, никак не переносят — точно так же сидят по домам с кондиционерами
😁12👍10🔥4🌚1
#prog #rust
У Linux есть чудесная технология eBPF. Если коротко, то это виртуальная машина с JIT-компиляцией, которая работает в контексте ядра и потому имеет доступ к его структурам и может вызываться на входе и выходе конкретных функций ядра, а также верификатор, который проверяет, что программы, исполняемые на этой виртуальной машине, всегда завершаются.
К сожалению, непосредственное взаимодействие со всем API, которое ядро для этого даёт, осуществляется через системный вызов bpf:
Работать с этим интерфейсом не очень удобно, поэтому разработчики ядра также предоставляют библиотеку libbpf, которая даёт более внятный интерфейс — с отдельными функциями и внятными аргументами для того, что в системном вызове делается через комбинацию аргументов и заполнение
В силу крайне высоких ограничений на размеры BPF-программ сколько-нибудь насыщенную логику непосредственно в них писать нереально — на практике в них, как правило, только собирают информацию и передают их в юзерспейс. Для (в том числе) поддержки этой задачи специально для BPF-кода есть мапы (maps). К ним можно осуществлять доступ как и из BPF-кода, так и из юзерспейса. Разновидностей мап несколько, с разными возможностями. Один из типов — кольцевой буфер (ringbuf), для асинхронной передачи произвольных данных и поддерживающий многопоточный доступ.
В юзерспейс-составляющей API этого кольцевого буфера есть несколько функций. Одна из них опрашивает кольцевой буфер на предмет наличия новых данных и вызывает на них пользовательские коллбеки. Эти коллбеки предварительно регистрируются функцией
, где
Как видите, разработчики libbpf избежали позорной ошибки дизайна qsort и предоставили возможность привязать к коллбеку произвольный контекст, который передаётся в него аргументом.
Библиотека libbpf-rs, хоть и не полностью покрывает API libbpf, всё же даёт возможность регистрировать пользовательские коллбеки со стороны Rust:
Как видите, libbpf-rs даёт возможность прикреплять растовые замыкания. Но погодите-ка, как это работает, если сишное API работает только с указателями на функции, а растовые замыкания нельзя (по крайней мере, на стабильной версии) распилить на код и захваченные данные?
libbpf-rs использует этот контекстный параметр! Именно, метод
Так что вот неожиданный пример, как дальновидность со стороны изначальных разработчиков может быть использована так, как они и не думали.
У Linux есть чудесная технология eBPF. Если коротко, то это виртуальная машина с JIT-компиляцией, которая работает в контексте ядра и потому имеет доступ к его структурам и может вызываться на входе и выходе конкретных функций ядра, а также верификатор, который проверяет, что программы, исполняемые на этой виртуальной машине, всегда завершаются.
К сожалению, непосредственное взаимодействие со всем API, которое ядро для этого даёт, осуществляется через системный вызов bpf:
int bpf(int cmd, union bpf_attr *attr, unsigned int size);
Работать с этим интерфейсом не очень удобно, поэтому разработчики ядра также предоставляют библиотеку libbpf, которая даёт более внятный интерфейс — с отдельными функциями и внятными аргументами для того, что в системном вызове делается через комбинацию аргументов и заполнение
bpf_attr. Ожидаемо, для этой библиотеки есть обёртка для использования из Rust: libbpf-rs. Она предоставляет более дружелюбный к Rust API и использует его систему типов для того, чтобы соблюдать инварианты, которые в сишном коде записаны лишь в документации.В силу крайне высоких ограничений на размеры BPF-программ сколько-нибудь насыщенную логику непосредственно в них писать нереально — на практике в них, как правило, только собирают информацию и передают их в юзерспейс. Для (в том числе) поддержки этой задачи специально для BPF-кода есть мапы (maps). К ним можно осуществлять доступ как и из BPF-кода, так и из юзерспейса. Разновидностей мап несколько, с разными возможностями. Один из типов — кольцевой буфер (ringbuf), для асинхронной передачи произвольных данных и поддерживающий многопоточный доступ.
В юзерспейс-составляющей API этого кольцевого буфера есть несколько функций. Одна из них опрашивает кольцевой буфер на предмет наличия новых данных и вызывает на них пользовательские коллбеки. Эти коллбеки предварительно регистрируются функцией
ring_buffer__add:int ring_buffer__add(
struct ring_buffer *rb,
int map_fd,
ring_buffer_sample_fn sample_cb,
void *ctx
)
, где
ring_buffer_sample_fn является typedef-ом на тип коллбека:typedef int (*ring_buffer_sample_fn)(void *ctx, void *data, size_t size);
Как видите, разработчики libbpf избежали позорной ошибки дизайна qsort и предоставили возможность привязать к коллбеку произвольный контекст, который передаётся в него аргументом.
Библиотека libbpf-rs, хоть и не полностью покрывает API libbpf, всё же даёт возможность регистрировать пользовательские коллбеки со стороны Rust:
impl<'slf, 'cb> struct RingBufferBuilder<'slf, 'cb> {
pub fn add<NewF>(
&mut self,
map: &'slf MapHandle,
callback: NewF
) -> Result<&mut Self>
where
NewF: FnMut(&[u8]) -> i32 + 'cb;
}Как видите, libbpf-rs даёт возможность прикреплять растовые замыкания. Но погодите-ка, как это работает, если сишное API работает только с указателями на функции, а растовые замыкания нельзя (по крайней мере, на стабильной версии) распилить на код и захваченные данные?
libbpf-rs использует этот контекстный параметр! Именно, метод
RingBufferBuilder::add боксит замыкание и сохраняет его в векторе в виде Box<dyn FnMut(&[u8]) -> i32 + 'cb>, а в методе RingBufferBuilder::build итерируется по сохранённым коллбекам, переводит их в тонкие сырые указатели через Box::into_raw(Box::new(callback)) и передаёт его как параметр ctx в ring_buffer__new или ring_buffer__add. В обоих случаях в качестве сишного коллбека передаётся эта функция, которая просто распаковывает настоящий коллбек из контекста и вызывает его:unsafe extern "C" fn call_sample_cb(
ctx: *mut c_void,
data: *mut c_void,
size: c_ulong
) -> i32 {
let callback_struct = ctx as *mut RingBufferCallback<'_>;
let callback = unsafe { (*callback_struct).cb.as_mut() };
let slice = unsafe {
slice::from_raw_parts(
data as *const u8,
size as usize,
)
};
callback(slice)
}
Так что вот неожиданный пример, как дальновидность со стороны изначальных разработчиков может быть использована так, как они и не думали.
❤19👍8🤯3🔥2😐1