• [技术干货] 2020-10-06:java中垃圾回收器让工作线程停顿下来是怎么做的?
    2020-10-06:java中垃圾回收器让工作线程停顿下来是怎么做的?#福大大架构师每日一题#
  • [Java] synchronized关键字
    synchronized也叫同步锁,是Java里面的关键字。我们可以猜测到synchronized原理也JVM虚拟机有关联。synchronized锁的是对象。对象里面有一个叫做监视锁(monitor)的东西,监视锁依赖操作系统的互斥锁(Mutex Lock)。操作系统切换线程其实就是从用户态编程核心态(cpu的两种状态)。这个代价有点高,所以synchronized这个重量级锁后面也引进了偏向锁和轻量级锁。加锁(监视锁monitor)过程分析():当monitor的进入数为0,线程A进入monitor的进入数为1线程B想进入该monitor就会被阻塞。线程A可以重复进入该monitor,所以synchronized是可重入锁,和Lock实现的锁一样。程序验证public class SynchronizedTest {    private static  int i = 0;    public static void main(String[] args) {    test();   }   public static void test(){    synchronized (SynchronizedTest.class){        synchronized (SynchronizedTest.class){            i++;            }        }    }}运行结果程序正常运行,没有报错synchronized可以修饰方法以及代码块,代码块就是上面重入锁的例子。修饰方法public class SynchronizedTest {    static int n = 100;    final static CountDownLatch start = new CountDownLatch(n);    private static  int i = 0;    public static void main(String[] args) throws InterruptedException {        for (int j = 0; j < n; j++) {            Thread thread = new Thread(new addNoSynchronized());            thread.start();        }        start.await();        System.out.println(i);    }    public static class addSynchronized implements Runnable{        @Override        public void run() {            addSynchronized();        }        public static synchronized void addSynchronized(){            for (int j = 0; j < 1000; j++) {                i++;            }            start.countDown();        }    }}运行结果Copy100000如果去掉 synchronized 关键字的话,运行结果大概率不是 100000,因为线程不安全问题。
  • [其他] 【告警】CPU使用率超过阈值
    【问题现象】  在前端FIM界面上观察集大部分节点的CPU使用率持续飚高,具体情况见下图:【问题分析】 1. 通过TOP命令查看gaussdb 进程的CPU使用率,可以观察到在CPU使用高峰的时候可以达到1000%+,当时截图没有保留,下图为示例。2. 使用 top -H -p pid查找进程内占用的CPU百分比较高的线程。3. 根据线程的PID找到对应的语句select * from pgxc_thread_wait_status t1, pgxc_stat_activity a1 where t1.query_id = a1.query_id and lwtid = xxxx ;通过上面的信息可以看到有两个长时间执行不完的查询语句导致的。【解决办法】临时将语句先kill 掉,观察集群CPU使用率明显下降。对于用户调试性的语句可以配置异常规则, 设置参数statement_timeout,执行超时的语句数据库会自动给杀掉。配置多租户,限制单个用户的CPU使用率,避免一个语句将所有CPU都消耗掉。
  • [Atlas300] 昇腾A800-3000无法开启超过32线程问题
    【功能模块】使用昇腾A800-3000服务器+8张atlas300卡场景。在适用分布式负载均衡款框架场景时,无法开启超过32进程。【操作步骤&问题现象】1、新建进程,初始化设置设备deviceID 2、分配到deviceID =17时,程序卡住不动。【截图信息】卡住不动,无法有效展示【日志信息】(可选,上传日志内容或者附件)报错信息如下。
  • [技术干货] 从存储端高并发之线程池,聊聊GaussDB(for MySQL) 的高扩展性
  • [Atlas 300] 日志使用汇总
    运行报错最近看到许多小伙伴在运行目标检测demo时出错,并显示500002的报错信息。500002为GE内部错误,但看此信息难以定位问题,因此需要借助日志功能。日志查看一般安装完toolkit后,系统会自动拉起log日志服务。此时通过 ps -ef | grep slogd,以及 ps -ef | grep log-daemon。可以看到这两个进程的运行情况以及所属组为HwHiAiUser。这时运行代码后,日志会直接记录在 /var/log/npu/slogd/device-*, 以及  /var/log/npu/slogd/host-*中。等级设置日志级别设置有2种方式:1、修改 /var/log/npu/conf/slog/slog.conf 文件中各个板块的等级,并重启服务器 reboot或者重启slogd进程,log-daemon进程。2、直接使用adc工具修改日志等级。    2.1、设置环境变量:(根据实际安装路径设置!)export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/xxx-linux_gccx.x.x/toolkit/lib64:${LD_LIBRARY_PATH} export PATH=/usr/local/Ascend/ascend-toolkit/latest/xxx-linux_gccx.x.x/toolkit/tools/ide_daemon/bin:$PATH    2.2、设置全局级日志级别:adc --host 服务器的IP地址:端口号 --log 'SetLogLevel(0)[level]' --device id 举例:adc --host 192.168.1.2:22118 --log 'SetLogLevel(0)[info]' --device 0    2.3、设置模块级的日志级别的命令如下:adc --host 服务器的IP地址:端口号 --log 'SetLogLevel(2)[enable/disable]' --device id 举例:adc --host 192.168.1.2:22118 --log 'SetLogLevel(2)[enable]' --device 0重启日志1、重启slogd进程    1.1、ps -ef | grep slogd    1.2、kill -9 进程ID    1.3、等待日志自动重启,或切换至HwHiAiUser,启动日志 /usr/local/Ascend/driver/tools/slogd2、重启log-daemon进程    2.1、ps -ef | grep log-daemon    2.2、kill -9 进程ID    2.3、等待日志自动重启,或切换至HwHiAiUser,启动日志 /usr/local/Ascend/driver/tools/log-daemon详细例子根据最上方报错信息,可以知道问题出在模型推理失败。因此根据上面的介绍,进入host侧日志存放路径,1、cd /var/log/npu/slogd/host-*2、vim host-0_20200927024816631.log (日志命名方式为 host-芯片id-时间戳.log)3、/ERROR -> 回车 -> n(下一个匹配位置)(搜索ERROR关键字)4、结果如下:5、分析:第一个标注位置表示 输入数据个数要求为1,但是实际传入了2个。第二标注表示 模型运行失败,第三个标注表示 aclmdlExecute接口失败并返回。因此这个可以定位模型输入有误。6、查看输入模型的pb文件/prototxt文件,截图如下:tf模型INPUTS个数为1。caffe模型INPUTS个数为2。与报错信息相符。因此问题可能是加载了tensorflow模型,要求的输入个数是1。但是代码执行了 使用caffe模型推理的分支,导致实际输入个数与预期输入输入不符。7、查看目标检测代码。AclProcess.cpp中,ModelInfer为调用om模型进行推理。可以看到196行初始化 inputSizes 的vector长度为1,但是通过198行的判断,可能会向此vector加入数据。因此关键在于 modelType,这个全局变量。8、查看 modelType 关键字,定位问题,在命令行输入时,未指定 -t=0或1 模型类型,因此默认为 -t=0,使用caffe进行推理。在执行时,inputSizes 的长度为2,与om模型要求不符合,导致 aclmdlExecute接口报错。9、解决方法,通过 -t=1指定使用 tf模型:10、原图:参考链接以下链接详细介绍了Atlas300产品日志系统的使用以及常见问题: @hw@haha 大佬分享的Atlas小百科V2:https://bbs.huaweicloud.com/forum/thread-70008-1-1.html。第七章节内容。以及Atlas300产品文档:https://support.huaweicloud.com/lr-A300_3000_3010/atlaslog_24_0001.html。CANN日志参考章节内容。
  • [技术干货] 怎样安全地关闭MySQL实例
    分析了mysqld进程关闭的过程,以及如何安全、缓和地关闭MySQL实例,对这个过程不甚清楚的同学可以参考下。关闭过程:1、发起shutdown,发出  SIGTERM信号2、有必要的话,新建一个关闭线程(shutdown thread)如果是客户端发起的关闭,则会新建一个专用的关闭线程如果是直接收到 SIGTERM 信号进行关闭的话,专门负责信号处理的线程就会负责关闭工作,或者新建一个独立的线程负责这个事当无法创建独立的关闭线程时(例如内存不足),MySQL Server会发出类似下面的告警信息:Error: Can't create thread to kill server3、MySQL Server不再响应新的连接请求关闭TCP/IP网络监听,关闭Unix Socket等渠道4、逐渐关闭当前的连接、事务空闲连接,将立刻被终止;当前还有事务、SQL活动的连接,会将其标识为 killed,并定期检查其状态,以便下次检查时将其关闭;(参考 KILL 语法)当前有活跃事务的,该事物会被回滚,如果该事务中还修改了非事务表,则已经修改的数据无法回滚,可能只会完成部分变更;如果是Master/Slave复制场景里的Master,则对复制线程的处理过程和普通线程也是一样的;如果是Master/Slave复制场景里的Slave,则会依次关闭IO、SQL线程,如果这2个线程当前是活跃的,则也会加上 killed 标识,然后再关闭;Slave服务器上,SQL线程是允许直接停止当前的SQL操作的(为了避免复制问题),然后再关闭该线程;在MySQl 5.0.80及以前的版本里,如果SQL线程当时正好执行一个事务到中间,该事务会回滚;从5.0.81开始,则会等待所有的操作结束,除非用户发起KILL操作。当Slave的SQL线程对非事务表执行操作时被强制 KILL了,可能会导致Master、Slave数据不一致;5、MySQL Server进程关闭所有线程,关闭所有存储引擎;刷新所有表cache,关闭所有打开的表;每个存储引擎各自负责相关的关闭操作,例如MyISAM会刷新所有等待写入的操作;InnoDB会将buffer pool刷新到磁盘中(从MySQL 5.0.5开始,如果innodb_fast_shutdown不设置为 2 的话),把当前的LSN记录到表空间中,然后关闭所有的内部线程。6、MySQL Server进程退出关于KILL指令从5.0开始,KILL 支持指定  CONNECTION | QUERY两种可选项:KILL CONNECTION和原来的一样,停止回滚事务,关闭该线程连接,释放相关资源;KILL QUERY则只停止线程当前提交执行的操作,其他的保持不变;提交KILL操作后,该线程上会设置一个特殊的 kill标记位。通常需要一段时间后才能真正关闭线程,因为kill标记位只在特定的情况下才检查:1、执行SELECT查询时,在ORDER BY或GROUP BY循环中,每次读完一些行记录块后会检查 kill标记位,如果发现存在,该语句会终止;2、执行ALTER TABLE时,在从原始表中每读取一些行记录块后会检查 kill 标记位,如果发现存在,该语句会终止,删除临时表;3、执行UPDATE和DELETE时,每读取一些行记录块并且更新或删除后会检查 kill 标记位,如果发现存在,该语句会终止,回滚事务,若是在非事务表上的操作,则已发生变更的数据不会回滚;4、GET_LOCK() 函数返回NULL;5、INSERT DELAY线程会迅速内存中的新增记录,然后终止;6、如果当前线程持有表级锁,则会释放,并终止;7、如果线程的写操作调用在等待释放磁盘空间,则会直接抛出“磁盘空间满”错误,然后终止;8、当MyISAM表在执行REPAIR TABLE 或 OPTIMIZE TABLE 时被 KILL的话,会导致该表损坏不可用,指导再次修复完成。安全关闭MySQL几点建议想要安全关闭 mysqld 服务进程,建议按照下面的步骤来进行:0、用具有SUPER、ALL等最高权限的账号连接MySQL,最好是用 unix socket 方式连接;1、在5.0及以上版本,设置innodb_fast_shutdown = 1,允许快速关闭InnoDB(不进行full purge、insert buffer merge),如果是为了升级或者降级MySQL版本,则不要设置;2、设置innodb_max_dirty_pages_pct = 0,让InnoDB把所有脏页都刷新到磁盘中去;3、设置max_connections和max_user_connections为1,也就最后除了自己当前的连接外,不允许再有新的连接创建;4、关闭所有不活跃的线程,也就是状态为Sleep  且 Time 大于 1 的线程ID;5、执行 SHOW PROCESSLIST  确认是否还有活跃的线程,尤其是会产生表锁的线程,例如有大数据集的SELECT,或者大范围的UPDATE,或者执行DDL,都是要特别谨慎的;6、执行 SHOW ENGINE INNODB STATUS 确认History list length的值较低(一般要低于500),也就是未PURGE的事务很少,并且确认Log sequence number、Log flushed up to、Last checkpoint at三个状态的值一样,也就是所有的LSN都已经做过检查点了;7、然后执行FLUSH LOCKAL TABLES 操作,刷新所有 table cache,关闭已打开的表(LOCAL的作用是该操作不记录BINLOG);8、如果是SLAVE服务器,最好是先关闭 IO_THREAD,等待所有RELAY LOG都应用完后,再关闭 SQL_THREAD,避免 SQL_THREAD 在执行大事务被终止,耐心待其全部应用完毕,如果非要强制关闭的话,最好也等待大事务结束后再关闭SQL_THREAD;9、最后再执行 mysqladmin shutdown。10、紧急情况下,可以设置innodb_fast_shutdown = 1,然后直接执行 mysqladmin shutdown 即可,甚至直接在操作系统层调用 kill 或者 kill -9 杀掉 mysqld 进程(在innodb_flush_log_at_trx_commit = 0 的时候可能会丢失部分事务),不过mysqld进程再次启动时,会进行CRASH RECOVERY工作,需要有所权衡。啰嗦那么多,其实正常情况下执行 mysqladmin shutdown 就够了,如果发生阻塞,再参考上面的内容进行分析和解决吧,哈哈:)
  • [其他] 【OS】集群出现大量(5W+)僵尸进程,OS load高,引发os重启
    【问题现象】操作系统版本:Redhat 7.4 / x86GaussDB版本:GaussDB A 6.5.1.5集群出现大量(5W+)僵尸进程,OS load高,引发os重启,现场排查发现是后台的secbox反复在重启引发的该僵尸进程【问题分析】1、通过观察CMA的日志,发现secbox在不停的反复重启2、secbox重启时,会调用date命令,而secbox出错退出,这些date命令就会变成僵尸进程3、进一步调查secbox重启原因发现,该集群的mount信息中,对于/var/log/Bigdata这一级目录单独做了挂载:4、产品资料手册里面描述的,对于日志盘需要按照下列方式挂载:5、未按照4中描述方式挂载时,由于和secbox.conf内容不匹配,进而引发secbox反复重启。6、现场通过手动调整secbox.conf,增加如下列,进行规避【解决方案】由于OS的挂盘配置不当,导致secbox后台服务反复重启,引发大量僵尸进程,在业务高峰期时,僵尸进程积压,导致OS重启。现场通过手动调整secbox.conf,增加如下列,进行规避
  • [问题求助] graph.config的写法
    【目的】为了实现多线程并行处理,提高处理帧率【操作步骤&问题现象】以两个线程为例,代码中构造了两个inference(id=639,id=666)处理类(xxx_inference.cpp,xxx_inference.h)当graph.config中的connects写法如下:  connects {     src_engine_id: 487     src_port_id: 0     target_engine_id: 639     target_port_id: 0   }   connects {     src_engine_id: 487     src_port_id: 1     target_engine_id: 666     target_port_id: 0   }   connects {     src_engine_id: 639     src_port_id: 0     target_engine_id: 641     target_port_id: 0   }   connects {     src_engine_id: 666     src_port_id: 0     target_engine_id: 641     target_port_id: 1   }只有一个id=639的inference处理线程在运行;当graph.config中的connects写法如下:  connects {     src_engine_id: 487     src_port_id: 0     target_engine_id: 639     target_port_id: 0   }   connects {     src_engine_id: 487     src_port_id: 0     target_engine_id: 666     target_port_id: 0   }   connects {     src_engine_id: 639     src_port_id: 0     target_engine_id: 641     target_port_id: 0   }   connects {     src_engine_id: 666     src_port_id: 0     target_engine_id: 641     target_port_id: 0   }两个inference处理线程都在运行,但是同一数据同时传到了两个线程中,没有达到多线程处理的效果。【问题】所以在graph.config如何配置才能达到多线程并行处理目的?
  • [问题求助] inference engine中多线程实现数据的问题
    目的在inference engine中,采用多线程,提高AI Core使用效率描述在image engine中,有这么一段代码:do { hiai_ret = SendData(kSendDataPort, "EngineTrans", static_pointer_cast<void>(image_handle)); // when queue full, sleep if (hiai_ret == HIAI_QUEUE_FULL) { HIAI_ENGINE_LOG("queue full, sleep 200ms"); usleep(kSleepInterval); } } while (hiai_ret == HIAI_QUEUE_FULL);也就是说在向inference engine传递数据时,HIAI框架有维护一个数据传递队列QUEUE。问题HIAI_IMPL_ENGINE_PROCESS("xxx_inference",xxxInference, INPUT_SIZE)因此inference engine的HIAI_IMPL_ENGINE_PROCESS处理完成一次之后,再被HIAI调用开始下一次处理过程吗?如果在单个inference engine类中采用多线程,如何实现?如何主动取得image engine传递队列中数据并建立维护线程?如果采用多组功能完全相同的inference engine多线程处理同一image engine传递过来的数据,如下图所示,如何保证输出到同一个post engine时的处理结果序列和图像帧序列之间的对应关系?
  • [Atlas500] 【Atlas500/200】【DVPP抠图功能】通过多线程并行处理发挥不出1440fps的性能上限
    【功能模块】DVPP【操作步骤&问题现象】1、一批人脸数据(>30个),需要在1080p的大图上完成抠图2、对人脸数据分组,如6个一组,拉4-5个线程调用dvppCtl接口抠图,不能达到1440fps的性能3、该指标是在文档https://support.huaweicloud.com/adevg-A500pro_3000/atlasdevelopment_01_0220.html中公布的,但是测试为基于最新的ACL框架而是以前的Matrix框架测试,是否因框架不同导致性能指标无法复现?【截图信息】【日志信息】(可选,上传日志内容或者附件)
  • [技术干货] [转载]Python 并发编程之线程锁
    线程 --> 锁1、锁与GILGIL 是python 解释器全局锁2、同步锁多个线程抢占资源的情况:from threading import Thread import os,time def work():     global n     temp=n     time.sleep(0.1)     n=temp-1 if __name__ == '__main__':     n=100     l=[]     for i in range(100):         p=Thread(target=work)         l.append(p)         p.start()     for p in l:         p.join()     print(n) #结果可能为99import threading R=threading.Lock() R.acquire() ''' 对公共数据的操作 '''同步锁的引用:from threading import Thread,Lock import os,time def work():     global n     lock.acquire()     temp=n     time.sleep(0.1)     n=temp-1     lock.release() if __name__ == '__main__':     lock=Lock()     n=100     l=[]     for i in range(100):         p=Thread(target=work)         l.append(p)         p.start()     for p in l:         p.join()     print(n) #结果肯定为0,由原来的并发执行变成串行,牺牲了执行效率保证了数据安全互斥锁与join的区别:#不加锁:并发执行,速度快,数据不安全 from threading import current_thread,Thread,Lock import os,time def task():     global n     print('%s is running' %current_thread().getName())     temp=n     time.sleep(0.5)     n=temp-1 if __name__ == '__main__':     n=100     lock=Lock()     threads=[]     start_time=time.time()     for i in range(100):         t=Thread(target=task)         threads.append(t)         t.start()     for t in threads:         t.join()     stop_time=time.time()     print('主:%s n:%s' %(stop_time-start_time,n)) ''' Thread-1 is running Thread-2 is running ...... Thread-100 is running 主:0.5216062068939209 n:99 ''' #不加锁:未加锁部分并发执行,加锁部分串行执行,速度慢,数据安全 from threading import current_thread,Thread,Lock import os,time def task():     #未加锁的代码并发运行     time.sleep(3)     print('%s start to run' %current_thread().getName())     global n     #加锁的代码串行运行     lock.acquire()     temp=n     time.sleep(0.5)     n=temp-1     lock.release() if __name__ == '__main__':     n=100     lock=Lock()     threads=[]     start_time=time.time()     for i in range(100):         t=Thread(target=task)         threads.append(t)         t.start()     for t in threads:         t.join()     stop_time=time.time()     print('主:%s n:%s' %(stop_time-start_time,n)) ''' Thread-1 is running Thread-2 is running ...... Thread-100 is running 主:53.294203758239746 n:0 ''' #有的同学可能有疑问:既然加锁会让运行变成串行,那么我在start之后立即使用join,就不用加锁了啊,也是串行的效果啊 #没错:在start之后立刻使用jion,肯定会将100个任务的执行变成串行,毫无疑问,最终n的结果也肯定是0,是安全的,但问题是 #start后立即join:任务内的所有代码都是串行执行的,而加锁,只是加锁的部分即修改共享数据的部分是串行的 #单从保证数据安全方面,二者都可以实现,但很明显是加锁的效率更高. from threading import current_thread,Thread,Lock import os,time def task():     time.sleep(3)     print('%s start to run' %current_thread().getName())     global n     temp=n     time.sleep(0.5)     n=temp-1 if __name__ == '__main__':     n=100     lock=Lock()     start_time=time.time()     for i in range(100):         t=Thread(target=task)         t.start()         t.join()     stop_time=time.time()     print('主:%s n:%s' %(stop_time-start_time,n)) ''' Thread-1 start to run Thread-2 start to run ...... Thread-100 start to run 主:350.6937336921692 n:0 #耗时是多么的恐怖 '''3、死锁与递归锁进程也有死锁与递归锁,在进程那里忘记说了,放到这里一切说了额所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程,如下就是死锁死锁:from threading import Lock as Lock import time mutexA=Lock() mutexA.acquire() mutexA.acquire() print(123) mutexA.release() mutexA.release()解决方法,递归锁,在Python中为了支持在同一线程中多次请求同一资源,python提供了可重入锁RLock。这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。上面的例子如果使用RLock代替Lock,则不会发生死锁:递归锁:from threading import RLock as Lock import time mutexA=Lock() mutexA.acquire() mutexA.acquire() print(123) mutexA.release() mutexA.release()典型问题:科学家吃面死锁问题:import time from threading import Thread,Lock noodle_lock = Lock() fork_lock = Lock() def eat1(name):     noodle_lock.acquire()     print('%s 抢到了面条'%name)     fork_lock.acquire()     print('%s 抢到了叉子'%name)     print('%s 吃面'%name)     fork_lock.release()     noodle_lock.release() def eat2(name):     fork_lock.acquire()     print('%s 抢到了叉子' % name)     time.sleep(1)     noodle_lock.acquire()     print('%s 抢到了面条' % name)     print('%s 吃面' % name)     noodle_lock.release()     fork_lock.release() for name in ['哪吒','egon','yuan']:     t1 = Thread(target=eat1,args=(name,))     t2 = Thread(target=eat2,args=(name,))     t1.start()     t2.start()递归锁解决死锁问题:import time from threading import Thread,RLock fork_lock = noodle_lock = RLock() def eat1(name):     noodle_lock.acquire()     print('%s 抢到了面条'%name)     fork_lock.acquire()     print('%s 抢到了叉子'%name)     print('%s 吃面'%name)     fork_lock.release()     noodle_lock.release() def eat2(name):     fork_lock.acquire()     print('%s 抢到了叉子' % name)     time.sleep(1)     noodle_lock.acquire()     print('%s 抢到了面条' % name)     print('%s 吃面' % name)     noodle_lock.release()     fork_lock.release() for name in ['哪吒','egon','yuan']:     t1 = Thread(target=eat1,args=(name,))     t2 = Thread(target=eat2,args=(name,))     t1.start()     t2.start()
  • [其他] 【故障】ldapserver与krbserver进程故障。
    【问题现象】ldapserver与krbserver进程故障。产生ALM-12007告警。【分析过程】1.确认krb与ldap同时故障,krb依赖ldap,所以该问题实际为ldap故障。将范围圈定在ldap上。2.多节点环境,集群类型相同,操作系统一致,排除不同环境差异。3.执行ldd /usr/sbin/ldap,好坏节点结果一致。4.执行rpm -qa |grep ldap,好坏节点结果一致。5.至此确认环境无差异,推测为环境变量导致。【解决方案】重启失败节点的nodeagent进程。恢复被污染的环境变量。1.将失败节点的nodeagent kill掉。 2.重启一下nodeagent。切换到omm用户执行sh /opt/huawei/Bigdata/om-agent/nodeagent/bin/stop-agent.sh,注意不要source mppdb的环境变量。3.sh /opt/huawei/Bigdata/om-agent/nodeagent/bin/start-agent.sh4.重启后 再从界面启动下ldap实例。至此,问题解决。
  • [问题求助] 关于多线程提高处理速度的问题
    描述使用多线程同时处理多张图像以最大限度利用NPU的计算能力,提高处理速度问题实现过程需要采用以下哪种方式:(1)使用c++标准库创建多线程,将数据作为参数传递到线程内,每个线程内创建ai_model_manager,并init和process;(2)一个graph里面开启了多个processengine,使其自行进行多线程处理;如果是方式(1),当前交叉编译环境的支持哪个版本的c++标准库,是否支持c++11?如果是方式(2),是需要在graph.config中创建多个graph id不同,但内部功能一致的engine;或者只需要将engine属性中的thread_num修改为n就可以;又或者是其他的什么方式;
  • [其他] 【OS】【CPU】CPU高的高效排查手段
    1.top看哪个进程高,记pid2.top -H -p pid 查看这个进程里具体什么线程占用cpu3.gstack pid(线程id),可以看下这个语句的执行过程,是在干些什么事情。4.连到数据库,查用线程的id,查pgxc_thread_wait_status,可以找到对应语句的query_id整改掉该问题语句即可(杀掉-重写)。附自己开发的一个cpu高语句抓取脚本,在cpu高的gaussdb节点,sh gs_getcputop.sh脚本即可附件直接下载,修改为sh格式linux下 执行dos2unix 脚本名之后即可使用。