精华内容
下载资源
问答
  • 今天介绍一下生产队列中常用的队列配置,怎么设置队列中任务使得任务之间有个优先级关系,怎么动态指定任务发送的队列。 一、Celery队列配置简介 CELERY_QUEUES = ( Queue("celery", Exchange("celery"), routing_...
    今天介绍一下生产队列中常用的队列配置,怎么设置队列中任务使得任务之间有个优先级关系,怎么动态指定任务发送的队列。

    一、Celery队列配置简介

    CELERY_QUEUES = (
        Queue("celery", Exchange("celery"), routing_key="celery")
    )
    

    celery是设置的队列名
    Exchange 是交换机的名称
    routing_key 交换机跟队列交流的key
    简单讲一下流程就是 celery服务端从rabbitmq中指定的交换机拿到对应的数据,然后发送给有这个交换机的指定的队列。

    这个是celery默认的队列设置。

    现在我们加多一个队列,设置这个队列具备优先级属性。

    # 优先级队列设置
    CELERY_ACKS_LATE = True
    CELERYD_PREFETCH_MULTIPLIER = 1
    
    CELERY_QUEUES = (
        Queue("celery", Exchange("celery"), routing_key="celery"),
        Queue("celery_demo", Exchange("celery_demo"), routing_key="celery_demo", queue_arguments={'x-max-priority': 9})
    )
    

    可以看到队列配置加多了两个属性,以及设置了队列优先级数值queue_arguments最高为9。
    注意CELERY_ACKS_LATE,CELERYD_PREFETCH_MULTIPLIER这两个属性一定要加到配置里面,不然优先级属性不会生效。

    二、动态指定任务队列,设置优先级

    在提交任务的时候apply_async设置队列指定为优先级队列celery_demo,并且设置优先级为5

    from celery_test.task_register import *
    from celery import group
    from celery import chord
    
    sig = add.s(1, 1)
    sig.apply_async(queue='celery_demo',priority=5)
    

    三、执行 任务,对比结果

    为了更加方便进行对比,我们对注册一个任务,睡眠10s再进行相加

    @app.task
    def add_time(x, y):
        time.sleep(10)
        return x + y
    

    1、启动服务端监听任务

    在这里插入图片描述
    可以看到这个服务端监听了两个队列,默认的celery队列以及有优先级属性的celery_demo,从RabbitMQ也可以看出来,具有pri的是则是设置了优先级的队列。
    在这里插入图片描述

    2、执行任务

    为了方便进行对比优先级有没有生效,我们这里设置了三个任务,分别如下

    sig = add_time.s(1, 1)
    sig.apply_async(queue='celery')
    sig = add_time.s(2, 2)
    sig.apply_async(queue='celery')
    sig = add_time.s(3, 3)
    sig.apply_async(queue='celery')
    

    先看在默认队列的执行结果
    在这里插入图片描述
    可以看到这三个任务都是顺序执行,哪个任务先提交的就先执行哪个任务,这也符合没有优先级的时候。
    接着我们将这三个任务放到具有优先级队列celery_demo
    并且设置三个任务的优先级参数

    sig = add_time.s(1, 1)
    sig.apply_async(queue='celery_demo',priority=5)
    sig = add_time.s(2, 2)
    sig.apply_async(queue='celery_demo',priority=7)
    sig = add_time.s(3, 3)
    sig.apply_async(queue='celery_demo',priority=8)
    

    在这里插入图片描述
    可以看到先执行了任务1,然后执行了任务3,最后执行了任务2
    为什么会这样呢,不应该是优先级最高的任务3最先执行吗?
    这里我们要考虑一个问题,在当前我们的队列是空的,也就是在队列非阻塞的情况下,当然是哪个任务先到先提交,哪个任务就先执行。
    接着任务1在执行的时候sleep了10s,也就是把队列阻塞了10s中,这时候队列中还有任务2,任务3。
    这时候任务2.任务3就要进行排序了,怎么排序呢,就是根据priority设置的数值,谁大谁优先执行。
    这种只会在设置了优先级队列的时候才会进行这种排序,不然都是按照任务提交的顺序进行。

    可能会有人会问如果提交到优先级队列,但是不设置priority,会默认最高级还是最低级呢?
    OK,我们看一下结果

    sig = add_time.s(1, 1)
    sig.apply_async(queue='celery_demo',priority=5)
    sig = add_time.s(2, 2)
    sig.apply_async(queue='celery_demo')
    sig = add_time.s(3, 3)
    sig.apply_async(queue='celery_demo',priority=1)
    

    在这里插入图片描述
    从结果上来看队列会默认没有设置优先级的最晚执行,按照顺序执行。

    Celery队列的一些基础设置,优先级设置,动态指定队列就先讲到这里,如果有什么问题可以评论告诉我哦。

    我是一只前进的蚂蚁,希望能一起前行。

    如果对您有一点帮助,您的三连就是我创作的最大的动力,感谢!

    下一篇继续讲一下Celery怎么创建并行任务,工作流任务,工作链任务。

    注:如果本篇博客有任何错误和建议,欢迎各位指出,不胜感激!!!

    展开全文
  • FreeRTOS多优先级实现

    2020-05-10 18:04:25
    List_t pxReadyTasksLists[configMAX_PRIORITIES]是数组,数组下标代表任务优先级,任务创建是根据设置任务优先级插入到对应下标的列表根节点上,如下。 要支持多优先级,就是再任务切换时让pxCurrentTCB指向最高...

    如何实现任务多优先级

    FreeRTOS中,数字优先级越小,逻辑优先级也越小,空闲任务优先级为0.
    List_t pxReadyTasksLists[configMAX_PRIORITIES]是数组,数组下标代表任务优先级,任务创建是根据设置的任务优先级插入到对应下标的列表根节点上,如下。
    在这里插入图片描述
    要支持多优先级,就是再任务切换时让pxCurrentTCB指向最高优先级的TCB即可,之前时手动再任务1、任务2来回切换,现在问题就是怎么找到优先级最高的就绪任务TCB。有2套方法,软件通用方法和硬件指令方法

    软件通用方法和硬件指令方法

    通过configUSE_PORT_OPTIMISED_TASK_SELECTION指定使用软件通用方法还是硬件指令方法,代码再task.c

    #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )//使用通用方法
    
    	/* uxTopReadyPriority 是全局变量,保存着最高优先级 */
    	#define taskRECORD_READY_PRIORITY( uxPriority )														\
    	{																									\
    		if( ( uxPriority ) > uxTopReadyPriority )														\
    		{																								\
    			uxTopReadyPriority = ( uxPriority );														\
    		}																								\
    	} /* taskRECORD_READY_PRIORITY */
    
    	/*-----------------------------------------------------------*/
    
    	#define taskSELECT_HIGHEST_PRIORITY_TASK()															\
    	{																									\
    		/* 从高到底依次寻找非空的列表根节点下标 */								\
    		while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) )						\
    		{																								\
    			configASSERT( uxTopReadyPriority );															\
    			--uxTopReadyPriority;																		\
    		}																								\
    																										\
    		/* 更新pxCurrentTCB 和*/									\
    		listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) );		\
    	} /* taskSELECT_HIGHEST_PRIORITY_TASK */
    
    	/*-----------------------------------------------------------*/
    
    	/* 对于软件方式这里做空*/
    	#define taskRESET_READY_PRIORITY( uxPriority )
    	#define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )
    
    #else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
    
    	/* 硬件指令方式 */
    
    	/* 根据uxPriority来更新uxTopReadyPriority,记录下最高优先级*/
    	#define taskRECORD_READY_PRIORITY( uxPriority )	portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority )
    
    	/*-----------------------------------------------------------*/
    
    	#define taskSELECT_HIGHEST_PRIORITY_TASK()														\
    	{																								\
    	UBaseType_t uxTopPriority;																		\
    																									\
    		/* 寻找优先级最高的任务TCB来更新pxCurrentTCB */							\
    		portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority );								\
    		configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 );		\
    		listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) );		\
    	} /* taskSELECT_HIGHEST_PRIORITY_TASK() */
    
    	/*-----------------------------------------------------------*/
    
    	/* 清除uxTopReadyPriority的uxPriority 位. */
    	#define taskRESET_READY_PRIORITY( uxPriority )														\
    	{																									\
    		if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 )	\
    		{																								\
    			portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) );							\
    		}																								\
    	}
    
    #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
    
    

    下面看着几个port接口

    #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) \
                 ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
                 
    #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) \
                 ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
    

    可以看到硬件方式是把uxTopReadyPriority 看作一个位图,每位代表一个优先级,一共32bit,任务就绪是就把对应位置1,反之清0.
    在这里插入图片描述
    所以获得最高就绪优先级的硬件方法如下(利用clz指令,计算一个变量从高位开始第一次出现1的位前面0的个数,上图clz(uxReadyPriorities)=6)

    #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities)\
            uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) )
    
    展开全文
  • 创建一个位图结构(位图结构存在的目的就是为了高效地获得就绪表中最高优先级任务,位图的特性就是高效),任务准备好时,就以优先级作为索引设置就绪表对应位为1,调度函数只需要找到为1的最小索引,然后对比该...

      笔者在嵌入式领域深耕6年,对嵌入式项目构建,BLDC电机控制,产品上位机开发以及产品量产和产品售后维护有多年工作经验。经验分享,从0到1, 让我带你从实际工作的角度走进嵌入式成长之路。

      原创不易欢迎大家关注我的微信公众号嵌入式工程师成长之路扫下面二维码
                         在这里插入图片描述
    所有文章总目录:【电子工程师 qt工程师】

    原创视频总目录:【电子工程师 qt工程师】

    本文概述:

      对于有很多任务,如果只通过时间片来轮转调度,系统的实时性也不会很强,所有需要使用优先级,也就是如果高优先级的任务就绪了就先调度到高优先级,以保证系统更高的实时性。
      怎么实现这个机制呢?创建一个位图结构(位图结构存在的目的就是为了高效地获得就绪表中最高优先级的任务,位图的特性就是高效),任务准备好时,就以优先级作为索引设置就绪表对应位为1,调度函数只需要找到为1的最小索引,然后对比该任务是否和当前任务相同,如果不相同,直接切换过去即可。这里需要注意:只有调用系统延时函数,才能将当前任务对应的位图位清0。如果不调用系统延时函数,该任务会一直运行,假如任务3的优先级是0,也就是优先级最高,如果任务函数内部没有调用过系统延时函数,那么系统不会发生任何调度。

    1.位图概述

    位图是一组连续的标志位,每一位标志用于标识某种状态的有无。
    在这里插入图片描述

    2.操作接口

    • 初始化:将所有位清0。
      在这里插入图片描述
    • 置1操作:给定某个位置,可以将其设置为1。
    • 清0操作:给定某个位置,可以将其清0。
    • 查找第一个置位的位置(从第0位到最高位依次查找)。
      在这里插入图片描述查找算法:
      (1)移位测试法,这种方法比较慢,但代码理解起来很简单。
      在这里插入图片描述(2)查表法,效率高,但代码理解起来比较难。

    3.优先级的引入

      CPU、事件、资源都是有限的,但任务却有非常多,在同一个时刻,怎样分配CPU、事件以及各种资源呢?
      可以在初始化一个任务时,给每个任务设置一个优先级。在调度函数中实现一种基于优先级的分发机制。
    在这里插入图片描述

    4.CPU优先级

      可以创建一个任务就绪表(位图),根据优先级来设置该位图中的位以表示这个任务可以调度了。在调度函数中,我们只要查表,从第0位查到最后一位(优先级也是从高到低)找到该位图中第一个为1的位,然后将CPU交给它。
    在这里插入图片描述

    5.实现过程

    (1)给任务添加优先级字段

    // 任务结构:包含了一个任务的所有信息
    typedef struct _tTask {
        tTaskStack * stack;
    
        // 任务延时计数器
        uint32_t delayTicks;
    
        // 任务的优先级
        uint32_t prio;
    }tTask;
    

    (2)添加优先级位图表

    // 任务优先级的标记位置结构
    tBitmap taskPrioBitmap;
    
    tTask * taskTable[TINYOS_PRO_COUNT];
    

    (3)修改调度算法

    void tTaskSched (void) 
    {   
        tTask * tempTask;
    
        // 进入临界区,以保护在整个任务调度与切换期间,不会因为发生中断导致currentTask和nextTask可能更改
        uint32_t status = tTaskEnterCritical();
    
        // 如何调度器已经被上锁,则不进行调度,直接退bm
        if (schedLockCount > 0) 
        {
            tTaskExitCritical(status);
            return;
        }
    
        // 找到优先级最高的任务,如果其优先级比当前任务的还高,那么就切换到这个任务
        tempTask = tTaskHighestReady();
        if (tempTask != currentTask) 
        {
            nextTask = tempTask;
            tTaskSwitch();   
        }
    
        // 退出临界区
        tTaskExitCritical(status); 
    }
    

    6.代码

    (1)main.c

    #include "tinyOS.h"
    #include "ARMCM3.h"
    
    // 当前任务:记录当前是哪个任务正在运行
    tTask * currentTask;
    
    // 下一个将即运行的任务:在进行任务切换前,先设置好该值,然后任务切换过程中会从中读取下一任务信息
    tTask * nextTask;
    
    // 空闲任务
    tTask * idleTask;
    
    // 任务优先级的标记位置结构
    tBitmap taskPrioBitmap;
    
    tTask * taskTable[TINYOS_PRO_COUNT];
    
    // 调度锁计数器
    uint8_t schedLockCount;
    
    void tTaskInit (tTask * task, void (*entry)(void *), void *param, uint32_t prio, uint32_t * stack)
    {
        *(--stack) = (unsigned long)(1<<24);                // XPSR, 设置了Thumb模式,恢复到Thumb状态而非ARM状态运行
        *(--stack) = (unsigned long)entry;                  // 程序的入口地址
        *(--stack) = (unsigned long)0x14;                   // R14(LR), 任务不会通过return xxx结束自己,所以未用
        *(--stack) = (unsigned long)0x12;                   // R12, 未用
        *(--stack) = (unsigned long)0x3;                    // R3, 未用
        *(--stack) = (unsigned long)0x2;                    // R2, 未用
        *(--stack) = (unsigned long)0x1;                    // R1, 未用
        *(--stack) = (unsigned long)param;                  // R0 = param, 传给任务的入口函数
        *(--stack) = (unsigned long)0x11;                   // R11, 未用
        *(--stack) = (unsigned long)0x10;                   // R10, 未用
        *(--stack) = (unsigned long)0x9;                    // R9, 未用
        *(--stack) = (unsigned long)0x8;                    // R8, 未用
        *(--stack) = (unsigned long)0x7;                    // R7, 未用
        *(--stack) = (unsigned long)0x6;                    // R6, 未用
        *(--stack) = (unsigned long)0x5;                    // R5, 未用
        *(--stack) = (unsigned long)0x4;                    // R4, 未用
    
        task->stack = stack;                                // 保存最终的值
        task->delayTicks = 0;
        task->prio = prio;                                  // 设置任务的优先级
    
        taskTable[prio] = task;                             // 填入任务优先级表
        tBitmapSet(&taskPrioBitmap, prio);                  // 标记优先级位置中的相应位
    }
    
    tTask * tTaskHighestReady (void) 
    {
        uint32_t highestPrio = tBitmapGetFirstSet(&taskPrioBitmap);
        return taskTable[highestPrio];
    }
    
    void tTaskSchedInit (void)
    {
        schedLockCount = 0;
    }
    
    void tTaskSchedDisable (void) 
    {
        uint32_t status = tTaskEnterCritical();
    
        if (schedLockCount < 255) 
        {
            schedLockCount++;
        }
    
        tTaskExitCritical(status);
    }
    
    void tTaskSchedEnable (void) 
    {
        uint32_t status = tTaskEnterCritical();
    
        if (schedLockCount > 0) 
        {
            if (--schedLockCount == 0) 
            {
                tTaskSched(); 
            }
        }
    
        tTaskExitCritical(status);
    }
    
    void tTaskSched (void) 
    {   
        tTask * tempTask;
    
        // 进入临界区,以保护在整个任务调度与切换期间,不会因为发生中断导致currentTask和nextTask可能更改
        uint32_t status = tTaskEnterCritical();
    
        // 如何调度器已经被上锁,则不进行调度,直接退bm
        if (schedLockCount > 0) 
        {
            tTaskExitCritical(status);
            return;
        }
    
        // 找到优先级最高的任务,如果其优先级比当前任务的还高,那么就切换到这个任务
        tempTask = tTaskHighestReady();
        if (tempTask != currentTask) 
        {
            nextTask = tempTask;
            tTaskSwitch();   
        }
    
        // 退出临界区
        tTaskExitCritical(status); 
    }
    
    void tTaskSystemTickHandler () 
    {
        // 检查所有任务的delayTicks数,如果不0的话,减1。
        int i;   
        uint32_t status = tTaskEnterCritical();
    
        for (i = 0; i < TINYOS_PRO_COUNT; i++) 
        {
    				if (taskTable[i] == 0)
    					continue;
            if (taskTable[i]->delayTicks > 0)
            {
                taskTable[i]->delayTicks--;
            }
            else 
            {
                tBitmapSet(&taskPrioBitmap, i);
            }
        }
        tTaskExitCritical(status);
    
        // 这个过程中可能有任务延时完毕(delayTicks = 0),进行一次调度。
        tTaskSched();
    }
    
    void tTaskDelay (uint32_t delay) {
       // 配置好当前要延时的ticks数
        uint32_t status = tTaskEnterCritical();
        currentTask->delayTicks = delay;
        tBitmapClear(&taskPrioBitmap, currentTask->prio);
        tTaskExitCritical(status);
    
        // 然后进行任务切换,切换至另一个任务,或者空闲任务
        // delayTikcs会在时钟中断中自动减1.当减至0时,会切换回来继续运行。
        tTaskSched();
    }
    
    void tSetSysTickPeriod(uint32_t ms)
    {
      SysTick->LOAD  = ms * SystemCoreClock / 1000 - 1; 
      NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);
      SysTick->VAL   = 0;                           
      SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
                       SysTick_CTRL_TICKINT_Msk   |
                       SysTick_CTRL_ENABLE_Msk; 
    }
    
    void SysTick_Handler () 
    {
        tTaskSystemTickHandler();
    }
    
    int task1Flag;
    void task1Entry (void * param) 
    {
        tSetSysTickPeriod(10);
        for (;;) 
        {
            task1Flag = 1;
            tTaskDelay(1);
            task1Flag = 0;
            tTaskDelay(1);
        }
    }
    
    int task2Flag;
    void task2Entry (void * param) 
    {
        for (;;) 
        {
            task2Flag = 1;
            tTaskDelay(1);
            task2Flag = 0;
            tTaskDelay(1);
        }
    }
    
    // 任务1和任务2的任务结构,以及用于堆栈空间
    tTask tTask1;
    tTask tTask2;
    tTaskStack task1Env[1024];
    tTaskStack task2Env[1024];
    
    // 用于空闲任务的任务结构和堆栈空间
    tTask tTaskIdle;
    tTaskStack idleTaskEnv[1024];
    
    void idleTaskEntry (void * param) {
        for (;;)
        {
            // 空闲任务什么都不做
        }
    }
    
    int main () 
    {
        // 优先初始化tinyOS的核心功能
        tTaskSchedInit();
    
        // 初始化任务1和任务2结构,传递运行的起始地址,想要给任意参数,以及运行堆栈空间
        tTaskInit(&tTask1, task1Entry, (void *)0x11111111, 0, &task1Env[1024]);
        tTaskInit(&tTask2, task2Entry, (void *)0x22222222, 1, &task2Env[1024]);
    
        // 创建空闲任务
        tTaskInit(&tTaskIdle, idleTaskEntry, (void *)0, TINYOS_PRO_COUNT - 1, &idleTaskEnv[1024]);
        
        // 这里,不再指定先运行哪个任务,而是自动查找最高优先级的任务运行
        nextTask = tTaskHighestReady();
    
        // 切换到nextTask, 这个函数永远不会返回
        tTaskRunFirst();
        return 0;
    }
    

    (2)switch.c和上一个版本一样
    (3)tBitmap.c

    #include "tLib.h"
    
    /**********************************************************************************************************
    ** Function name        :   tBitmapInit
    ** Descriptions         :   初始化bitmap将所有的位全清0
    ** parameters           :   无
    ** Returned value       :   无
    ***********************************************************************************************************/
    void tBitmapInit (tBitmap * bitmap) 
    {
    	bitmap->bitmap = 0;
    }
    
    /**********************************************************************************************************
    ** Function name        :   tBitmapPosCount
    ** Descriptions         :   返回最大支持的位置数量
    ** parameters           :   无
    ** Returned value       :   最大支持的位置数量
    ***********************************************************************************************************/
    uint32_t tBitmapPosCount (void) 
    {
    	return 32;
    }
    
    /**********************************************************************************************************
    ** Function name        :   tBitmapSet
    ** Descriptions         :   设置bitmap中的某个位
    ** parameters           :   pos 需要设置的位
    ** Returned value       :   无
    ***********************************************************************************************************/
    void tBitmapSet (tBitmap * bitmap, uint32_t pos)
    {
    	bitmap->bitmap |= 1 << pos;
    }
    
    /**********************************************************************************************************
    ** Function name        :   tBitmapClear
    ** Descriptions         :   清除bitmap中的某个位
    ** parameters           :   pos 需要清除的位
    ** Returned value       :   无
    ***********************************************************************************************************/
    void tBitmapClear (tBitmap * bitmap, uint32_t pos)
    {
    	bitmap->bitmap &= ~(1 << pos);
    }
    
    /**********************************************************************************************************
    ** Function name        :   tBitmapGetFirstSet
    ** Descriptions         :   从位图中第0位开始查找,找到第1个被设置的位置序号
    ** parameters           :   无
    ** Returned value       :   第1个被设置的位序号
    ***********************************************************************************************************/
    uint32_t tBitmapGetFirstSet (tBitmap * bitmap) 
    {
    	static const uint8_t quickFindTable[] =     
    	{
    	    /* 00 */ 0xff, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    	    /* 10 */ 4,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    	    /* 20 */ 5,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    	    /* 30 */ 4,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    	    /* 40 */ 6,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    	    /* 50 */ 4,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    	    /* 60 */ 5,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    	    /* 70 */ 4,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    	    /* 80 */ 7,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    	    /* 90 */ 4,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    	    /* A0 */ 5,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    	    /* B0 */ 4,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    	    /* C0 */ 6,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    	    /* D0 */ 4,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    	    /* E0 */ 5,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    	    /* F0 */ 4,    0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
    	};
    
    	if (bitmap->bitmap & 0xff)
        {
            return quickFindTable[bitmap->bitmap & 0xff];         
        }
        else if (bitmap->bitmap & 0xff00)
        {
            return quickFindTable[(bitmap->bitmap >> 8) & 0xff] + 8;        
        }
        else if (bitmap->bitmap & 0xff0000)
        {
            return quickFindTable[(bitmap->bitmap >> 16) & 0xff] + 16;        
        }
        else if (bitmap->bitmap & 0xFF000000)
        {
            return quickFindTable[(bitmap->bitmap >> 24) & 0xFF] + 24;
        }
        else
        {
            return tBitmapPosCount();
        }
    }
    

    (4)tLib.h

    #ifndef TLIB_H
    #define TLIB_H
    
    // 标准头文件,里面包含了常用的类型定义,如uint32_t
    #include <stdint.h>
    
    // 位图类型
    typedef struct 
    {
    	uint32_t bitmap;
    }tBitmap;
    
    /**********************************************************************************************************
    ** Function name        :   tBitmapInit
    ** Descriptions         :   初始化bitmap将所有的位全清0
    ** parameters           :   无
    ** Returned value       :   无
    ***********************************************************************************************************/
    void tBitmapInit (tBitmap * bitmap);
    
    /**********************************************************************************************************
    ** Function name        :   tBitmapPosCount
    ** Descriptions         :   返回最大支持的位置数量
    ** parameters           :   无
    ** Returned value       :   最大支持的位置数量
    ***********************************************************************************************************/
    uint32_t tBitmapPosCount (void);
    
    /**********************************************************************************************************
    ** Function name        :   tBitmapSet
    ** Descriptions         :   设置bitmap中的某个位
    ** parameters           :   pos 需要设置的位
    ** Returned value       :   无
    ***********************************************************************************************************/
    void tBitmapSet (tBitmap * bitmap, uint32_t pos);
    
    /**********************************************************************************************************
    ** Function name        :   tBitmapClear
    ** Descriptions         :   清除bitmap中的某个位
    ** parameters           :   pos 需要清除的位
    ** Returned value       :   无
    ***********************************************************************************************************/
    void tBitmapClear (tBitmap * bitmap, uint32_t pos);
    
    /**********************************************************************************************************
    ** Function name        :   tBitmapGetFirstSet
    ** Descriptions         :   从位图中第0位开始查找,找到第1个被设置的位置序号
    ** parameters           :   无
    ** Returned value       :   第1个被设置的位序号
    ***********************************************************************************************************/
    uint32_t tBitmapGetFirstSet (tBitmap * bitmap);
    
    #endif /* TLIB_H */
    

    (5)tConfig.h

    #ifndef TCONFIG_H
    #define TCONFIG_H
    
    #define	TINYOS_PRO_COUNT				32						// TinyOS任务的优先级序号
    
    #endif /* TCONFIG_H */
    
    展开全文
  • 准备工作导入numpyimport numpy as np示例数据本文以二分类任务为例,通常我们的model会输出预测的概率,得到概率后需要进行后续的处理,比如:• 根据阈值,将概率大于某个阈值的label设置为1,小于阈值的设置为0 ....

    dadb09898981ef8b91fbb622dbcf482f.png

    Numpy 功能十分强大,很多我们想要的复杂操作都有实现。 今天分享几个数据分析中经常需要用到的重要函数。 掌握这些函数可以帮助我们保持代码整洁并且避免重复造轮子。

    准备工作

    导入numpy

    738b39830b25913c7cd231cc132ac074.png
    import numpy as np

    示例数据

    本文以二分类任务为例,通常我们的model会输出预测的概率,得到概率后需要进行后续的处理,比如:

    • 根据阈值,将概率大于某个阈值的label设置为1,小于阈值的设置为0 • 在模型诊断过程中,找出满足某些条件的样本

    本文使用的示例数据如下:

    predict_prob = np.array([0.1,0.3,0.7,0.4,0.9])

    where()

    np.where() 方法可以帮助我们找到array中满足条件的元素的位置。现在我们可以使用np.where()找出所有预测概率大于0.5的的元素了:

    predict_prob = np.array([0.1,0.3,0.7,0.4,0.9])
    np.where(predict_prob > 0.5)
    # output:array([2, 4]),)

    如果我们想将所有概率大于0.5的元素替换为1,否则替换为0,该怎么做呢?

    一个 简单粗暴的方式 是先用上面的方法分别找出array中概率大于或者小于0.5的索引,然后再对这些位置的元素重新赋值。

    其实,np.where() 一个函数就能完成所有的操作,只需要添加两个参数:

    • 第一个参数是满足条件替换的值 • 第二个参数是不满足条件替换的值

    predict_prob = np.array([0.1,0.3,0.7,0.4,0.9])
    np.where(predict_prob > 0.5, 1, 0)
    # output: array([0, 0, 1, 0, 1])

    argmin()、argmax()、argsort()

    np.argmin()、np.argmax()方法会返回array中最小或最大的元素索引,对示例数据运行结果如下:

    predict_prob = np.array([0.1,0.3,0.7,0.4,0.9])
    
    np.argmax(predict_prob)
    # output: 4
    np.argmin(predict_prob)
    # output: 0

    我们成功找到了array中最大最小的元素索引,那怎样找到前n个最大的或最小的值呢?

    现在该轮到np.sort()上场了

    predict_prob = np.array([0.1,0.3,0.7,0.4,0.9])
    np.argsort(predict_prob)
    # output: array([0, 1, 3, 2, 4])

    np.argsort()方法还支持多维数据的排序,感兴趣的可以自行查看 Numpy官方文档 [1]

    intersect1d()

    intersect1d()要做的是,它会找出两个array中的交集,这个函数和前面的几个函数不同,返回的不是索引位置,而是array中的实际值。

    本函数我们使用新的 示例数据:

    arr1 = np.array([1,2,4,4,6])
    arr2 = np.array([2,3,4,5,6])

    现在,我们可以使用intersect1d()找出两个数组共同的元素了:

    np.intersect1d(arr1, arr2)
    # output: array([2, 4, 6])
    展开全文
  • 第二篇文章从任务如何切换开始讲起,引出RTOS内核中的就绪列表、优先级表,一层一层为你揭开RTOS内核优先级抢占式调度方法的神秘面纱。 RTOS内功修炼记(二)—— 优先级抢占调度到底是怎么回事? 第三篇文章讲述...
  • 任务状态转换

    千次阅读 2012-06-08 15:38:00
    程序中需要一个高优先级任务每执行完自身代码便挂起5ms,但是当收到外界事件时提前唤醒任务,一直用sleep(5),怎么着都不能实现【因为想要任务从延迟态转向就绪态,只有等延迟时间到期】; 假如从悬置态(或叫阻塞...
  • 第二篇文章从任务如何切换开始讲起,引出RTOS内核中的就绪列表、优先级表,一层一层为你揭开RTOS内核优先级抢占式调度方法的神秘面纱。RTOS内功修炼记(二)—— 优先级抢占调度到底是怎么回事?第三篇文章讲述了R...
  • 读了一下下freeRTOS的代码,结合代码过一下freeRTOS调度器是怎么工作的。 vTaskStartScheduler 创建完用户的各种任务之后,调用函数...可以看出idle task的任务优先级设置为portPRIVILEGE_BIT, 而portPRI...
  • 第二篇文章从任务如何切换开始讲起,引出RTOS内核中的就绪列表、优先级表,一层一层为你揭开RTOS内核优先级抢占式调度方法的神秘面纱。 RTOS内功修炼记(二)—— 优先级抢占调度到底是怎么回事? 第三篇文章讲述...
  • 第二篇文章从任务如何切换开始讲起,引出RTOS内核中的就绪列表、优先级表,一层一层为你揭开RTOS内核优先级抢占式调度方法的神秘面纱。 RTOS内功修炼记(二)—— 优先级抢占调度到底是怎么回事? 第三篇文章讲述...
  • 我们为什么要用甘特图? 因为在进行项目管理时,我们需要对项目进度进行整体的把握,也需要对项目内各项...新建项目,填写项目名称,设置工作日、优先级等。 创建好任务,把项目分解成小的任务,预估完成该项目需要
  • 上一节讲到M3任务切换是基于PendSV异常的,这一节就着重讲一下这个PendSV异常优先级设置以及它是怎么进行触发的,然后说一下接下来的讲解思路。 PendSV异常的优先级设置和触发 PendSV优先级设置比较简单,往PendSV...
  • taskSpawn

    千次阅读 2010-01-15 20:00:00
    taskspawn 分配一个任务时,参数中有优先级,堆栈大小,我要怎么来写啊?刚刚搞这个东西。 我看例子中优先级大都是90,我要是创建多个任务时,都写90行吗? 还有堆栈大小我要根据什么来设置啊?不一定要有taskSpawn...
  • 3. 除了优先级外,还有一个设置也是非常重要的,就是对于每个任务,你需要做工作量预估,预估什么呢,预估该任务开发完成所需的时间和人力等,敏捷里把这个预估叫做Story Point,故事点。 故事点这个概念现在争议...
  • 忍者 项目包含以下内容: 使用Javascript和Phaser 3来实现射击游戏;... 多任务并有效地管理时间和优先级; 熟练使用英语书面交流; 有效地将信息传达给技术人员。 我在第二天制作的游戏设计文档: 怎么玩 成为忍
  •  这章将向大家介绍.NET中的线程API,怎么样用C#创建线程,启动和停止线程,设置优先级和状态. <br /> 在.NET中编写的程序将被自动的分配一个线程.让我们来看看用C#编程语言创建线程并且继续学习线程的知识...
  •  在长期的开发实践中证明后台服务进程在某些机型,也有被杀死的可能,需要我们进一步需要进程优先级,怎么办,真正的“黑科技”来了,通过android系统提供的账号同步机制SyncAdapter来实现进程的优先级,...
  • Visual Studio程序员箴言中文扫描PDF

    热门讨论 2010-12-28 01:04:18
    技巧5.25 为任务列表中的用户任务分配优先级 118 技巧5.26 在任务列表中创建和查看todo注释 118 技巧5.27 在任务列表中创建快捷方式 119 技巧5.28 在任务列表中显示hack、undone和自定义标记 120 技巧5.29 ...
  • Visual Studio程序员箴言--详细书签版

    热门讨论 2012-10-16 20:37:39
    技巧2.7 设置文档、选定的文本或者只是当前行的格式 30 技巧2.8 保留制表符或者插入空格 30 技巧2.9 将空格转换为制表符和将制表符转换为空格 30 技巧2.10 从文本编辑器工具栏上增加或减少行缩进 31 技巧...
  • FAQ(持续更新)

    2021-01-08 12:27:51
    只需给server task设置一个callback,callback里状态码和错误码的定义与client task是一样的,但server task不会出现dns错误。 能不能不回复 可以。任何时候调用server task的noreply()方法,那么...
  • 且可以设置优先级</li><li>可以在父子组件任务间前进后退切换任务</li><li>render方法可以返回多元素(即可以返回数组)</li><li>支持异常边界处理异常</li></ul> 它的调用栈如下: 关于...
  •  本书针对大多数日常的oracle database 11g数据库管理任务,全面覆盖dba行业知识,并将理论与实践相结合,旨在为初中级dba提供高效运行数据库所需的方方面面的知识,帮助他们从oracle公司发行的大量资料中找到自己...
  • Init 帮助 Android 应用调度复杂的任务流(如应用初始化流程),如下一节图示的那种任务流,处理类型、优先级、多进程(像是每个进程都会执行application的onCreate),任务依赖,提高应用启动效率。 尽管Init...
  • 软件工程教程

    热门讨论 2012-07-06 23:10:29
    用例只描述参与者和系统在交互过程中做些什么,并不描述怎么做。 用例图 关联关系 用例图 泛化关系 用例图 泛化关系 用例图 用例图 用例图 用例用于什么情况? 不知道什么情况不用用例 如果没有用到用例,...
  • 存储系统为了更好的服务,经常会保证高优先级任务优先执行。当多个作业或用户访问存储系统时,如何保证优先级和公平性 1.3.1 最大频率栈 1.3.2 给定一个链表,删除链表的倒数第N个节点,并且返回链表的头结点 ...
  • # DIFS > PIFS > SIFS,因此AP总比普通节点具有更高的访问信道的优先级(间隔越小优先级越高) # # 802.11 DCF使用CSMA/CA的方法来避免碰撞,在发送包之前,发送端会等待一个DIFS时间, # 如果在这段期间內侦测到...
  • 这允许浏览器为不同的task source设置不同的优先级,比如为用户交互设置更高优先级来使用户感觉流畅。 <h4><code>Jobs and Job Queues规范 本来应该接着上面Event Loop的话题继续深入,讲macro-task和...
  • 3.5.2 设置死锁优先级 121 第4章 表 123 4.1 表基础 123 4.1.1 创建表 126 4.1.2 为既有表添加列 126 4.1.3 修改列定义 127 4.1.4 创建计算列 128 4.1.5 减少NULL列的存储空间 129 4.1.6 删除表中...
  • 【多线程】线程池对任务的处理 85 【多线程】线程池的状态 86 线程池的状态说明 86 各个状态之间的转换 86 【多线程】什么是线程池?如果让你设计一个动态大小的线程池,如何设计,应该有哪些方法? 87 【多线程】...
  • vc++ 应用源码包_1

    热门讨论 2012-09-15 14:22:12
    任务管理器应该大家都很熟悉,论坛里也有好多的任务管理器的源码,解决CListCtr刷新时滚动条跳到开始处。 VC++实现网络连接查看器源码 非常好的一个实例,把网络连接的UDP/TCP都插入到CList控件中显示出来。 VC++...

空空如也

空空如也

1 2 3
收藏数 43
精华内容 17
关键字:

任务优先级怎么设置