You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LSF API的lsb_submit是否线程安全?多线程调用异常求助

关于LSF集群lsb_submit API线程安全性的问题

我的应用尝试通过3个线程并发调用lsb_submit向LSF集群提交作业,调用时进程要么因段错误终止,要么打印如下提示:

Conflict parameter LSB_SUB_PROJECT_NAME - Ignored.
Conflict parameter LSB_SUB_JOB_DESCRIPTION - Ignored.
Conflict parameter LSB_SUB_USER_GROUP - Ignored.
Conflict parameter LM_PROJECT - Ignored.

但在单线程中顺序调用lsb_submit时,作业提交可成功完成。

请问:

  1. lsb_submit是否非线程安全?
  2. 有没有办法让该API实现线程安全?
  3. 是否存在线程安全版本?

以下是复现问题的最小化代码:

int func() {

    struct submit req;    
    memset(&req, 0, sizeof(req));
    struct submitReply  reply;  

    for (int i = 0; i < LSF_RLIM_NLIMITS; i++) {   
        req.rLimits[i] = DEFAULT_RLIMIT;
    }

    req.options = 0;
    req.options2 = 0;
    req.beginTime = 0;
    req.termTime  = 0;
    req.numProcessors = 1; 
    req.maxNumProcessors = 1;    

    std::string cmd = "ls"; 
    req.command = new char[cmd.size()+1];
    cmd.copy(req.command, cmd.size());
    req.command[cmd.size()] = '\0'; 
    
    int jobId = lsb_submit(&req, &reply);
    if (jobId < 0) {  
      std::cout << "\nFailed submit ";
      /*handle*/ 
    } else {
      std::cout << "\nSuccess submit ";
    }
    return 1;
}

int main(int argc, char **argv) 
{
    if (lsb_init(argv[0]) < 0) {
        lsb_perror(NULL);
        exit(-1);
    }

    std::vector<std::future<int>> vec;
    for (int i=0; i<2; ++i) {
      vec.push_back(std::async(std::launch::async, func));
    }
    std::cout << "\nOutput = " << vec[0].get();
    std::cout << "\nOutput = " << vec[1].get();
}

每次运行程序的输出结果不同:

  • 有时会出现段错误:
$ ./a.out ls

*** Error in `./a.out': double free or corruption (fasttop): 0x00002ae760006440 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x81329)[0x2ae75a024329]
<>/lib/liblsf.so(+0x15253b)[0x2ae75910a53b]
<>/lib/liblsf.so(+0x152a9a)[0x2ae75910aa9a]
<>/lib/liblsf.so(callLimVarXdrSize_+0x650)[0x2ae75910bb70]
<>/lib/liblsf.so(callLim_+0x27)[0x2ae75910d417]
<>/lib/liblsf.so(+0x146e4a)[0x2ae7590fee4a]
<>/lib/liblsf.so(ls_getmastername+0x69)[0x2ae7590ff079]
<>/lib/libbat.so(getMasterName+0x170)[0x2ae758cae260]
<>/lib/libbat.so(+0xa5500)[0x2ae758c17500]
<>/lib/libbat.so(lsb_submit+0xeb)[0x2ae758c1b7eb]
./a.out[0x4036a3]
...
  • 有时会出现参数冲突提示但作业提交成功:
$ ./a.out ls

Aug  7 10:36:27 2024 32345 4 10.1 Conflict parameter LSB_SUB_PROJECT_NAME - Ignored.
Aug  7 10:36:27 2024 32345 4 10.1 Conflict parameter LSB_SUB_JOB_DESCRIPTION - Ignored.
Aug  7 10:36:27 2024 32345 4 10.1 Conflict parameter LM_PROJECT - Ignored.
Aug  7 10:36:27 2024 32345 4 10.1 Conflict parameter JOB_DESCRIPTION - Ignored.
Res = Job <480466> is submitted to default queue <>.

Success submit 1
Res = Job <480467> is submitted to default queue <>.

Success submit 1 

回答
  1. lsb_submit确实是非线程安全的
    从你遇到的段错误(double free/corruption)和参数冲突提示就能看出——这些都是多线程环境下共享资源竞争导致的典型问题。LSF的经典C API(包括lsb_submit)内部使用了全局状态变量,并发调用时会出现线程间的资源覆盖,从而引发内存错误或参数解析冲突。

  2. 实现线程安全的可行方案

  • 全局互斥锁:在所有线程调用lsb_submit前后加一把全局互斥锁,确保同一时间只有一个线程执行该API调用。示例代码如下:
#include <mutex>

std::mutex lsf_submit_mutex;

int func() {
    // ... 原有req初始化代码 ...

    std::lock_guard<std::mutex> lock(lsf_submit_mutex);
    int jobId = lsb_submit(&req, &reply);
    
    // ... 后续处理代码 ...
}

这种方式简单直接,但会牺牲并发性能,所有提交请求会变成串行执行。

  • 每个线程独立初始化LSF环境:部分LSF版本支持线程级别的环境初始化,你可以尝试在每个线程内调用lsb_init(而非主线程一次性初始化)。不过需要验证你的LSF版本是否支持这种用法,有些旧版本不支持线程级隔离。

  • 改用进程替代线程:如果性能要求允许,可以用多进程替代多线程提交作业,每个进程独立调用lsb_submit,完全避免线程间的资源竞争问题。

  1. 是否存在线程安全版本
    LSF的新版本提供了REST API(通过LSF Web Service),这是天然线程安全的,因为每个请求都是独立的HTTP调用,没有共享的全局状态。如果你的集群支持LSF Web Service,可以考虑改用REST API来实现并发提交。

另外,IBM官方文档明确说明:传统的LSF C API(包括lsb_submit)不保证线程安全性,并发调用需要用户自行处理同步。


内容的提问来源于stack exchange,提问作者bdd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 21:22:32