gpt4 book ai didi

rust - 如何在另一个Tokio运行时中创建Tokio运行时而没有出现 "Cannot start a runtime from within a runtime"错误?

转载 作者:行者123 更新时间:2023-12-03 11:24:03 31 4
gpt4 key购买 nike

我正在使用 rust_bert 汇总文本。我需要使用rust_bert::pipelines::summarization::SummarizationModel::new设置模型,该模型可以从互联网上获取模型。它使用 tokio 异步完成此操作,并且(我认为)我遇到的问题是我正在另一个Tokio运行时中运行Tokio运行时,如错误消息所示:

Downloading https://cdn.huggingface.co/facebook/bart-large-cnn/config.json to "/home/(censored)/.cache/.rustbert/bart-cnn/config.json"
thread 'main' panicked at 'Cannot start a runtime from within a runtime. This happens because a function (like `block_on`) attempted to block the current thread while the thread is being used to drive asynchronous tasks.', /home/(censored)/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.21/src/runtime/enter.rs:38:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
我试过运行与同步获取的模型
tokio::task::spawn_blocking
tokio::task::block_in_place
但他们俩都没有为我工作。 block_in_place发出的错误与好像不存在的错误相同,而且 spawn_blocking似乎对我似乎没有用。
我也尝试过使 summarize_text异步,但这并没有太大帮助。 Github问题
tokio-rs/tokio#2194
和Reddit帖子
"'Cannot start a runtime from within a runtime.' with Actix-Web And Postgresql"
看起来很相似(错误消息相同),但是它们对于找到解决方案并没有太大帮助。
我遇到的代码如下:
use egg_mode::tweet;
use rust_bert::pipelines::summarization::SummarizationModel;

fn summarize_text(model: SummarizationModel, text: &str) -> String {
let output = model.summarize(&[text]);
// @TODO: output summarization
match output.is_empty() {
false => "FALSE".to_string(),
true => "TRUE".to_string(),
}
}

#[tokio::main]
async fn main() {
let model = SummarizationModel::new(Default::default()).unwrap();

let token = egg_mode::auth::Token::Bearer("obviously not my token".to_string());
let tweet_id = 1221552460768202756; // example tweet

println!("Loading tweet [{id}]", id = tweet_id);
let status = tweet::show(tweet_id, &token).await;
match status {
Err(err) => println!("Failed to fetch tweet: {}", err),
Ok(tweet) => {
println!(
"Original tweet:\n{orig}\n\nSummarized tweet:\n{sum}",
orig = tweet.text,
sum = summarize_text(model, &tweet.text)
);
}
}
}

最佳答案

解决问题
这是一个简化的示例:

use tokio; // 1.0.2

#[tokio::main]
async fn inner_example() {}

#[tokio::main]
async fn main() {
inner_example();
}
thread 'main' panicked at 'Cannot start a runtime from within a runtime. This happens because a function (like `block_on`) attempted to block the current thread while the thread is being used to drive asynchronous tasks.', /playground/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.0.2/src/runtime/enter.rs:39:9
为避免这种情况,您需要在完全独立的线程上运行创建第二个Tokio运行时的代码。最简单的方法是使用 std::thread::spawn :
use std::thread;

#[tokio::main]
async fn inner_example() {}

#[tokio::main]
async fn main() {
thread::spawn(|| {
inner_example();
}).join().expect("Thread panicked")
}
为了提高性能,您可能希望使用线程池,而不是每次都创建一个新线程。为了方便起见,Tokio本身通过 spawn_blocking 提供了这样一个线程池:
#[tokio::main]
async fn inner_example() {}

#[tokio::main]
async fn main() {
tokio::task::spawn_blocking(|| {
inner_example();
}).await.expect("Task panicked")
}
在某些情况下,您不需要实际创建第二个Tokio运行时,而可以重用父运行时。为此,您将 Handle 传递给外部运行时。如果需要等待工作完成,则可以选择使用像 futures::executor 这样的轻量级执行程序来阻止结果:
use tokio::runtime::Handle; // 1.0.2

fn inner_example(handle: Handle) {
futures::executor::block_on(async {
handle
.spawn(async {
// Do work here
})
.await
.expect("Task spawned in Tokio executor panicked")
})
}

#[tokio::main]
async fn main() {
let handle = Handle::current();

tokio::task::spawn_blocking(|| {
inner_example(handle);
})
.await
.expect("Blocking task panicked")
}
也可以看看:
  • Do a synchronous http client fetch within an actix thread
  • How to create a dedicated threadpool for CPU-intensive work in Tokio?

  • 避免问题
    更好的方法是首先避免创建嵌套的Tokio运行时。理想情况下,如果库使用异步执行器,它也将提供直接异步功能,因此您可以使用自己的执行器。
    值得研究一下API,以查看是否存在非阻塞替代方案,如果没有,则在项目存储库中引发问题。
    您还可以重新组织代码,以使Tokio运行时不嵌套,而是顺序运行:
    struct Data;

    #[tokio::main]
    async fn inner_example() -> Data {
    Data
    }

    #[tokio::main]
    async fn core(_: Data) {}

    fn main() {
    let data = inner_example();
    core(data);
    }

    关于rust - 如何在另一个Tokio运行时中创建Tokio运行时而没有出现 "Cannot start a runtime from within a runtime"错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62536566/

    31 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com