精华内容
下载资源
问答
  • 控制节点角色的是Keepalived配置文件中的“priority”值,但并它并不控制所有节点的角色,另一个能改变节点角色的是在vrrp_script模块中设置的“weight”值,这两个选项对应的都是一个整数值,其中“weight”值可以...
  • Priority Nav Scroller是Priority +导航模式的插件。 当导航项不适合显示在屏幕上时,它们将被隐藏,并且可以滚动到视图中或使用控件。 安装 $ npm install priority - nav - scroller -- save - dev 用法 导入JS ...
  • 感谢使用过Android Priority JobQueue的每个人。 它是在没有JobScheduler的世界中设计的,RxJava并不流行,甚至Kotlin都不是公开诞生的。 今天,该项目中的大部分学习内容都属于WorkManager(Android官方的延迟...
  • Priority Job Queue is an implementation of a Job Queue specifically written for Android to easily schedule jobs (tasks) that run in the background, improving UX and application stability.
  • 本文简要介绍一种基于数组二叉堆实现的优先队列,定义的数据结构和实现的函数接口说明如下
  • redis-priority-queue是一个简单的工作队列,类似于具有以下新增功能: 可以添加具有优先级的项目(介于-9007199254740992和9007199254740992之间) 队列会自动进行重复数据删除(重复的项目在推送时会作废) ...
  • 主要介绍了c++优先队列(priority_queue)用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • data.priority-map-源码

    2021-05-15 07:29:24
    clojure.data.priority-map 以前是clojure.contrib.priority-map。 优先级映射与排序映射非常相似,但是排序映射生成按键排序的条目序列,而优先级映射生成按值排序的条目。 除了支持排序映射支持的所有功能之外...
  • C++ 中”priority_queue” 优先级队列实例详解 1. 简介 标准库队列使用了先进先出(FIFO)的存储和检索策略. 进入队列的对象被放置在尾部, 下一个被取出的元素则取自队列的首部. 标准库提供了两种风格的队列: FIFO ...
  • var priority = require ( 'node-priority' ) ; priority . set ( priority . Process , 0 , 10 , function ( err ) { if ( err ) throw err ; priority . get ( priority . Process , 0 , function ( err , prio...
  • npm install co-priority-queue 例子 与一个消费者排队: var co = require('co'); var Queue = require('co-priority-queue'); co(function *(){ var queue = new Queue; queue.push('a', 1); queue.push('b'...
  • 主要介绍了 STL priority_queue(优先队列)详解的相关资料,需要的朋友可以参考下
  • 修复android-priority-jobqueue-2.0.1这个开源库cursor没关闭的BUG
  • 脱机样本应用程序中级帖子涵盖了该应用程序:使用MVVM,RxJava,Room和Priority Job Queue构建脱机优先应用程序什么是脱机应用程序? 脱机应用程序(或“脱机优先应用程序”)使用户能够无缝地将涵盖此应用程序的...
  • matlab开发-priority

    2019-08-21 12:31:30
    matlab开发-priority。通过编程改变matlab进程的优先级。
  • priority_queue_c-源码

    2021-02-17 09:09:46
    priority_queue_c
  • 若需第三份,我也上传了,其中包含课设3(Priority_Donate)的报告和代码,欢迎下载。 课设最终成绩90+,不用担心质量。 最后一个提醒,每个学校OS课设不一样,我这个是将FCFS的线程调度方式改成优先级调度的方式。
  • 优先队列(Priority queue)

    千次阅读 2020-12-23 13:06:23
    while (i > 1 && h->nodes[j].priority > priority) { h->nodes[i] = h->nodes[j]; i = j; j = j / 2; } h->nodes[i].priority = priority; h->nodes[i].data = data; h->len++; } char *pop (heap_t *h) { int i, ...

    优先队列有点类似于队列,但有一个重要的区别:每个元素都以优先级级别添加到优先队列中,进行出队列操作时,具有最高优先级的元素将先出队列。也就是说,元素是按优先级顺序存储在队列中的,而不是按插入顺序存储的。

    任务:
    创建一个优先队列,必须至少支持两种操作:

    1. 入队列。 带有优先级(数字值)的元素添加到队列中。
    2. 队头出队列。 具有当前最高优先级的元素或元素之一出队并返回它。

    可以定义其他操作,例如peek(查找当前的最高优先级/队头元素是什么),merge(将两个优先级队列合并为一个)等。

    测试数据:

            Priority         Task
           ══════════   ════════════════
               3         Clear drains
               4         Feed cat
               5         Make tea
               1         Solve RC tasks
               2         Tax return
    

    C

    Using a dynamic array as a binary heap. Stores integer priority and a character pointer. Supports push and pop.

    #include <stdio.h>
    #include <stdlib.h>
     
    typedef struct {
        int priority;
        char *data;
    } node_t;
     
    typedef struct {
        node_t *nodes;
        int len;
        int size;
    } heap_t;
     
    void push (heap_t *h, int priority, char *data) {
        if (h->len + 1 >= h->size) {
            h->size = h->size ? h->size * 2 : 4;
            h->nodes = (node_t *)realloc(h->nodes, h->size * sizeof (node_t));
        }
        int i = h->len + 1;
        int j = i / 2;
        while (i > 1 && h->nodes[j].priority > priority) {
            h->nodes[i] = h->nodes[j];
            i = j;
            j = j / 2;
        }
        h->nodes[i].priority = priority;
        h->nodes[i].data = data;
        h->len++;
    }
     
    char *pop (heap_t *h) {
        int i, j, k;
        if (!h->len) {
            return NULL;
        }
        char *data = h->nodes[1].data;
     
        h->nodes[1] = h->nodes[h->len];
     
        h->len--;
     
        i = 1;
        while (i!=h->len+1) {
            k = h->len+1;
            j = 2 * i;
            if (j <= h->len && h->nodes[j].priority < h->nodes[k].priority) {
                k = j;
            }
            if (j + 1 <= h->len && h->nodes[j + 1].priority < h->nodes[k].priority) {
                k = j + 1;
            }
            h->nodes[i] = h->nodes[k];
            i = k;
        }
        return data;
    }
     
    int main () {
        heap_t *h = (heap_t *)calloc(1, sizeof (heap_t));
        push(h, 3, "Clear drains");
        push(h, 4, "Feed cat");
        push(h, 5, "Make tea");
        push(h, 1, "Solve RC tasks");
        push(h, 2, "Tax return");
        int i;
        for (i = 0; i < 5; i++) {
            printf("%s\n", pop(h));
        }
        return 0;
    }
    

    输出:

    Solve RC tasks
    Tax return
    Clear drains
    Feed cat
    Make tea
    

    通用数据类型

    header file:

    typedef struct _pq_node_t {
        long int key;
        struct _pq_node_t *next, *down;
    } pq_node_t, *heap_t;
     
    extern heap_t heap_merge(heap_t, heap_t);
    extern heap_t heap_pop(heap_t);
     
    #define NEW_PQ_ELE(p, k) \
        do { \
    	(p) = (typeof(p)) malloc(sizeof(*p)); \
    	((pq_node_t *) (p))->next = ((pq_node_t *) (p))->down = NULL; \
    	((pq_node_t *) (p))->key = (k); \
        } while (0)
     
    #define HEAP_PUSH(p, k, h) \
        NEW_PQ_ELE(p, k); \
        *(h) = heap_merge(((pq_node_t *) (p)), *(h))
    

    implementation:

    #include <stdlib.h>
    #include "pairheap.h"
     
    static heap_t add_child(heap_t h, heap_t g) {
        if (h->down != NULL)
    	g->next = h->down;
        h->down = g;
    }
     
    heap_t heap_merge(heap_t a, heap_t b) {
        if (a == NULL) return b;
        if (b == NULL) return a;
        if (a->key < b->key) {
    	add_child(a, b);
    	return a;
        } else {
    	add_child(b, a);
    	return b;
        }
    }
     
    /* NOTE: caller should have pointer to top of heap, since otherwise it won't 
     *       be reclaimed.  (we do not free the top.)
     */
    heap_t two_pass_merge(heap_t h) {
        if (h == NULL || h->next == NULL)
    	return h;
        else {
    	pq_node_t
    	    *a = h,
    	    *b = h->next,
    	    *rest = b->next;
    	a->next = b->next = NULL;
    	return heap_merge(heap_merge(a, b), two_pass_merge(rest));
        }
    }
     
    heap_t heap_pop(heap_t h) {
        return two_pass_merge(h->down);
    }
    

    usage:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include "pairheap.h"
     
    struct task {
        pq_node_t hd;
        char task[40];
    };
     
    void main() {
        heap_t heap = NULL;
        struct task *new;
     
        HEAP_PUSH(new, 3, &heap);
        strcpy(new->task, "Clear drains.");
     
        HEAP_PUSH(new, 4, &heap);
        strcpy(new->task, "Feed cat.");
     
        HEAP_PUSH(new, 5, &heap);
        strcpy(new->task, "Make tea.");
     
        HEAP_PUSH(new, 1, &heap);
        strcpy(new->task, "Solve RC tasks.");
     
        HEAP_PUSH(new, 2, &heap);
        strcpy(new->task, "Tax return.");
     
        while (heap != NULL) {
    	struct task *top = (struct task *) heap;
    	printf("%s\n", top->task);
    	heap = heap_pop(heap);
    	free(top);
        }
    }
    

    输出:

    Solve RC tasks.
    Tax return.
    Clear drains.
    Feed cat.
    Make tea.
    

    C++

    #include <iostream>
    #include <string>
    #include <queue>
    #include <utility>
     
    int main() {
      std::priority_queue<std::pair<int, std::string> > pq;
      pq.push(std::make_pair(3, "Clear drains"));
      pq.push(std::make_pair(4, "Feed cat"));
      pq.push(std::make_pair(5, "Make tea"));
      pq.push(std::make_pair(1, "Solve RC tasks"));
      pq.push(std::make_pair(2, "Tax return"));
     
      while (!pq.empty()) {
        std::cout << pq.top().first << ", " << pq.top().second << std::endl;
        pq.pop();
      }
     
      return 0;
    }
    

    输出:

    5, Make tea
    4, Feed cat
    3, Clear drains
    2, Tax return
    1, Solve RC tasks
    

    Go

    package main
     
    import (
        "fmt"
        "container/heap"
    )
     
    type Task struct {
        priority int
        name     string
    }
     
    type TaskPQ []Task
     
    func (self TaskPQ) Len() int { return len(self) }
    func (self TaskPQ) Less(i, j int) bool {
        return self[i].priority < self[j].priority
    }
    func (self TaskPQ) Swap(i, j int) { self[i], self[j] = self[j], self[i] }
    func (self *TaskPQ) Push(x interface{}) { *self = append(*self, x.(Task)) }
    func (self *TaskPQ) Pop() (popped interface{}) {
        popped = (*self)[len(*self)-1]
        *self = (*self)[:len(*self)-1]
        return
    }
     
    func main() {
        pq := &TaskPQ{{3, "Clear drains"},
            {4, "Feed cat"},
            {5, "Make tea"},
            {1, "Solve RC tasks"}}
     
        // heapify
        heap.Init(pq)
     
        // enqueue
        heap.Push(pq, Task{2, "Tax return"})
     
        for pq.Len() != 0 { 
            // dequeue
            fmt.Println(heap.Pop(pq))
        }
    }
    

    输出:

    {1 Solve RC tasks}
    {2 Tax return}
    {3 Clear drains}
    {4 Feed cat}
    {5 Make tea}
    

    Java

    import java.util.PriorityQueue;
     
    class Task implements Comparable<Task> {
        final int priority;
        final String name;
     
        public Task(int p, String n) {
            priority = p;
            name = n;
        }
     
        public String toString() {
            return priority + ", " + name;
        }
     
        public int compareTo(Task other) {
            return priority < other.priority ? -1 : priority > other.priority ? 1 : 0;
        }
     
        public static void main(String[] args) {
            PriorityQueue<Task> pq = new PriorityQueue<Task>();
            pq.add(new Task(3, "Clear drains"));
            pq.add(new Task(4, "Feed cat"));
            pq.add(new Task(5, "Make tea"));
            pq.add(new Task(1, "Solve RC tasks"));
            pq.add(new Task(2, "Tax return"));
     
            while (!pq.isEmpty())
                System.out.println(pq.remove());
        }
    }
    

    输出:

    1, Solve RC tasks
    2, Tax return
    3, Clear drains
    4, Feed cat
    5, Make tea
    

    Python

    Using PriorityQueue

    >>> import queue
    >>> pq = queue.PriorityQueue()
    >>> for item in ((3, "Clear drains"), (4, "Feed cat"), (5, "Make tea"), (1, "Solve RC tasks"), (2, "Tax return")):
      pq.put(item)
     
     
    >>> while not pq.empty():
      print(pq.get_nowait())
     
     
    (1, 'Solve RC tasks')
    (2, 'Tax return')
    (3, 'Clear drains')
    (4, 'Feed cat')
    (5, 'Make tea')
    >>> 
    

    Using heapq

    >>> from heapq import heappush, heappop, heapify
    >>> items = [(3, "Clear drains"), (4, "Feed cat"), (5, "Make tea"), (1, "Solve RC tasks"), (2, "Tax return")]
    >>> heapify(items)
    >>> while items:
      print(heappop(items))
     
     
    (1, 'Solve RC tasks')
    (2, 'Tax return')
    (3, 'Clear drains')
    (4, 'Feed cat')
    (5, 'Make tea')
    >>> 
    
    展开全文
  • C++中优先队列priority_queue的基础用法

    千次阅读 多人点赞 2020-09-12 17:28:51
    从定义可以看出,虽然要结构是三个参数,但是后两个参数带了默认值,所以针对于普通的数据类型,一般情况下指提供第1个参数就可以了,比如 priority_queue 实际上等价于 priority_queue, less>。 这三个参数的含义...

    前言

    学习优先队列之前先看个单词队列 queue, 这个单词的读法很多人都能读对吧,音标是 /kjuː/ ,再看一个双端队列 deque,它的音标是 /dek/,应该有人读错了吧,反正我是没读对,刚开始看见一次错一次,现在还好了,基本能记住怎么读了,可是这些队列怎么用呢?

    队列就不用多说了,一个先进先出的经典数据结构,那么优先队列是个什么鬼,其实它就是在队列的基础上加上优先两个字,想想怎样才能优先呢?没错——排队!只有排好了队伍才会有落后和优先之分,否则一团乱糟糟的,怎么才能分出优先的,所以优先队列一定应用了排序。

    可是排序要怎样实现呢?其实排序这个底层逻辑你是不用管的,你只要把想要的数据放到优先队列里,然后取出的必定是当前状态下最优的,当然,究竟什么是最优的条件是需要你来设定的,也就是说我们需要定义排序的规则。

    头文件

    优先队列 priority_queue 是队列 queue 的一个变种,头文件是#include <queue>,使用优先队列必须要包含这个头文件。

    结构定义

    优先队列的结构定义是一个模板类,需要提供三个类型参数:

    template<
        class T,
        class Container = std::vector<T>,
        class Compare = std::less<typename Container::value_type>
    > class priority_queue;
    

    从定义可以看出,虽然要结构是三个参数,但是后两个参数带了默认值,所以针对于普通的数据类型,一般情况下指提供第1个参数就可以了,比如 priority_queue<int> 实际上等价于 priority_queue<int, vector<int>, less<int>>

    这三个参数的含义分别为:数据类型,容器类型和比较函数,实际上优先队列就是维护了一个装有 T 类型元素的容器 Container,并在入队和出队时对容器内元素使用 Compare 比较函数进行了排序。

    这3个参数还要满足一定的要求,并且在使用过程中有些注意事项:

    • 如果类型 TContainer 容器中元素类型不一致,那么行为未定义,所以要避免这种情况。
    • Container 必须是序列容器,其实C++中序列容器很多的,比如std::arraystd::vectorstd::dequestd::list
    • Container 还必须要支持随机访问,并且有 front()push_back()pop_back() 等函数

    这样来看只有 std::vectorstd::deque 满足容器条件了,而优先队列中使用的默认参数也是 std::vector

    队列排序

    一直在说优先队列里使用了排序,而常用的容器是 std::verctor,那么究竟用的是什么排序,又是在什么时候进行的排序呢?实际上这里的排序并不是我们通常拿到数据后使用的冒泡排序、快速排序等,优先队列中的排序本质上是堆排序,但是它不是每次都进行完整的堆排序,而是通过 Container 维护了一个堆结构,每次入队和出队时都进行一次堆调整,所花时间为 log(n),所以用在数据量大的地方,速度比较快。

    优先队列使用

    当我们大概了解了优先队列的原理后,可以通过使用来进一步熟悉这个结构,下面来看几个例子。

    实现排序

    #include <iostream>
    #include <queue>
    using namespace std;
    
    void common_sort()
    {
        int source_data[10] = {3, 5, 8, 1, 10, 2, 9, 15, 13, 16};
    
        // 默认大根堆,实现由大到小排序
        priority_queue<int> q;
        for (auto n : source_data) q.push(n);
    
        while (!q.empty()) {
            cout << q.top() << endl;
            q.pop();
        }
    }
    

    priority_queue<int> 默认构建的是一个大根堆,所以每次从头取数据得到的是一个从大到小的队列排序

    albert@home-pc:/mnt/c++/datastruct$ g++ priorityqueue.cpp -o commonsort -std=c++11
    albert@home-pc:/mnt/c++/datastruct$ ./commonsort
    16
    15
    13
    10
    9
    8
    5
    3
    2
    1
    

    如果是完整排序使用优先队列就有些麻烦了,还不如直接调用 std::sort 函数,但是如果只取部分数据的话,优先队列还是非常方便快速的,比如下面这个问题。

    取出数组中最大的k个数

    这是一个经典的算法题,最容易想到的办法就是遍历,先找到最大的,然后排出这个数再找到最大的,这样找k次就好了,所需时间大概表示为 O(kN)

    还有一个方法是排序,使用 std::sort 排序后,然后依次取出前 k 个数就行了,排序使用快速排序的话可以达到所需时间为 O(Nlog(N)),其实这样已经很优秀了,但是还可以通过优先队列来加速,下面来写一下代码:

    #include <iostream>
    #include <queue>
    using namespace std;
    
    void max_k_num()
    {
        int source_data[10] = {3, 5, 8, 1, 10, 2, 9, 15, 13, 16};
        int k = 5;
    
        // 小根堆
        priority_queue<int, vector<int>, greater<int>> q;
        for (auto n : source_data) {
            if (q.size() == k) {
                if (n > q.top()) {
                    q.pop();
                    q.push(n);
                }
            }
            else q.push(n);
        }
    
        while (!q.empty()) {
            cout << q.top() << endl;
            q.pop();
        }
    }
    

    这里是定义了一个小根堆,堆顶是最小值,当有新元素大于堆顶元素时,并且队列中元素等于k个,需要移除堆顶元素,然后插入新的元素,这样就能保证优先队列中始终拥有最大的k个数,运行结果如下:

    albert@home-pc:/mnt/c++/datastruct$ g++ priorityqueue.cpp -o max_k_num -std=c++11
    albert@home-pc:/mnt/c++/datastruct$ ./max_k_num
    9
    10
    13
    15
    16
    

    因为这里控制堆的规模最大为k,所以这个算法的执行时间大概是O(Nlog(k)),绝大多数情况是优于快速排序的。

    自定义结构

    使用优先队列时常常要用到自定义结构,这时候就需要自己来写比较函数了,比如输出成绩最好的三个人的信息:

    #include <iostream>
    #include <queue>
    using namespace std;
    
    struct student {
        string name;
        int score;
    };
    
    struct cmp_custom {
        bool operator()(student& x, student& y) {
            return x.score > y.score;
        }
    };
    
    void max_k_score()
    {
        vector<student> stu_list = {{"Andy", 89}, {"Bella", 79}, {"Cary", 92}, {"Dick", 60}, {"Ray", 70}};
        int k = 3;
    
        // 小根堆
        priority_queue<student, vector<student>, cmp_custom> q;
        for (auto stu : stu_list) {
            if (q.size() == k) {
                if (stu.score > q.top().score) {
                    q.pop();
                    q.push(stu);
                }
            }
            else q.push(stu);
        }
    
        while (!q.empty()) {
            cout << q.top().name << ":" << q.top().score << endl;
            q.pop();
        }
    }
    

    输出结果如下,每个人的名字后面跟着分数,结果是分数最大的3个人的信息:

    albert@home-pc:/mnt/c++/datastruct$ g++ priorityqueue.cpp -o max_k_score -std=c++11
    albert@home-pc:/mnt/c++/datastruct$ ./max_k_score
    Bella:79
    Andy:89
    Cary:92
    

    自定义比较函数的另一种写法

    看到上个例子中自定义比较函数的写法比较怪,一般我们在排序时定义的比较函数使用lambda表达式就可以,而这里是不能直接这样写的,需要多转化一步,写成下面这种形式:

    auto cmp = [](student& x, student& y) { return x.score > y.score; };
    priority_queue<student, vector<student>, decltype(cmp)> q(cmp);
    

    虽然看起来还是有点怪,但总比下面这样要好看的多:

    struct cmp_custom {
        bool operator()(student& x, student& y) {
            return x.score > y.score;
        }
    };
    priority_queue<student, vector<student>, cmp_custom> q;
    

    常用函数

    优先队列的常用函数与队列类似,常用的有以下这些,如果想了解详细的用法,请戳在线文档

    函数名含义
    top访问队列的头部元素
    empty判断优先队列内是否有元素
    size返回优先队列内元素个数
    push向优先队列中插入元素
    emplace在优先队列中构造元素
    pop从优先队列头部弹出元素
    swap与其他容器交换元素

    总结

    • 优先队列在一些需要部分排序的场景可以加快访问速度,降低时间复杂度。
    • 优先队列加速所付出的代价就是构建堆结构所需的内存,时间和空间总是一对矛盾共同体
    • 以自定义结构作为元素的优先队列需要单独编写比较函数,可以使用lambda表达式,并用 decltype(cmp) 推导类型
    • 需要注意的是这里的优先队列定义,第三个参数的需要的是比较函数的参数类型,而不是比较函数,区分与 std::sort 的不同

    ==>> 反爬链接,请勿点击,原地爆炸,概不负责!<<==

    人在比较中奋进,同在比较中消亡,起初面临差距时会奋起直追,但是当努力过后发现距离反而越来越远时,便会麻木懈怠,曾经的努力没有用吗?我觉得不是,努力过不一定会成功,但是努力的过程已经印在了骨子里,这本身就是生活的一部分。你可以选择这条艰苦的路,同样也可以选择跳过,至于跳过时错失了什么,谁又知道呢?毕竟人生无法再来过,重新读档只发生在游戏世界中~

    展开全文
  • [scheduler]二. CPU priority概念以及原理

    千次阅读 2020-04-30 23:58:03
    什么CPU priority 使用场合在rt调度类中 因为在rt调度类中,只要抢占开启,高优先级的rt task会立即抢占低优先级task,并在当前CPU上运行。所以就有了rt task priority转化为CPU priority,即task优先运行在哪些CPU...
    什么是CPU priority
    1. 使用场合在rt调度类中
    2. 因为在rt调度类中,只要抢占开启,高优先级的rt task会立即抢占低优先级task,并在当前CPU上运行。所以就有了rt task priority转化为CPU priority,即task优先运行在哪些CPU上
    3. CPU priority的思想是 rt task优先级越高,CPU priority越低,rt task优先级越低,CPU priority越高,越容易被将要运行的rt task选择作为target cpu。
    4. 明白3之后,就知道为何如何维护一个CPU priority的概念了。即将有rt task运行的时候,肯定希望能够优先运行,肯定不希望将自己放置到有比自己优先级高的队列中。

    下面这张图,是CPU priority如何更新,task如何获取合理的CPU priority对应的cpumask:
    CPU priority整个框架图

    下面简单的看下其源码。

    初始化

    CPU priority初始化在初始化root domain的时候,即rd->cpupri,挂在rd下面,而rd又是全局性的,每个rq下面都有一个rd,但是都指向同一个rd。所以CPU priority结构体是每个CPU都在维护的一个全局性的结构体。

    #define CPUPRI_NR_PRIORITIES	(MAX_RT_PRIO + 2)
    
    #define CPUPRI_INVALID		-1
    #define CPUPRI_IDLE		 0
    #define CPUPRI_NORMAL		 1
    /* values 2-101 are RT priorities 0-99 */
    
    struct cpupri_vec {
    	atomic_t		count;
    	cpumask_var_t		mask;//
    };
    
    struct cpupri {
        /*哪个CPU priority对应的信息,包括引用次数和包含的cpumask。*/
    	struct cpupri_vec	pri_to_cpu[CPUPRI_NR_PRIORITIES];
    	int			*cpu_to_pri;
    };
    /**
     * cpupri_init - initialize the cpupri structure
     * @cp: The cpupri context
     *
     * Return: -ENOMEM on memory allocation failure.
     */
    int cpupri_init(struct cpupri *cp)
    {
    	int i;
    
    	for (i = 0; i < CPUPRI_NR_PRIORITIES; i++) {
    		struct cpupri_vec *vec = &cp->pri_to_cpu[i];
    
    		atomic_set(&vec->count, 0);
    		if (!zalloc_cpumask_var(&vec->mask, GFP_KERNEL))
    			goto cleanup;
    	}
    
    	cp->cpu_to_pri = kcalloc(nr_cpu_ids, sizeof(int), GFP_KERNEL);
    	if (!cp->cpu_to_pri)
    		goto cleanup;
        //为每个CPU维护一个这样一个数组
    	for_each_possible_cpu(i)
    		cp->cpu_to_pri[i] = CPUPRI_INVALID;
    
    	return 0;
    
    cleanup:
    	for (i--; i >= 0; i--)
    		free_cpumask_var(cp->pri_to_cpu[i].mask);
    	return -ENOMEM;
    }
    
    /**
     * cpupri_cleanup - clean up the cpupri structure
     * @cp: The cpupri context
     */
    void cpupri_cleanup(struct cpupri *cp)
    {
    	int i;
    
    	kfree(cp->cpu_to_pri);
    	for (i = 0; i < CPUPRI_NR_PRIORITIES; i++)
    		free_cpumask_var(cp->pri_to_cpu[i].mask);
    }
    
    
    task优先级如何转化为CPU priority
    /* Convert between a 140 based task->prio, and our 102 based cpupri */
    static int convert_prio(int prio)
    {
    	int cpupri;
    
    	if (prio == CPUPRI_INVALID)
    		cpupri = CPUPRI_INVALID;
    	else if (prio == MAX_PRIO)
    		cpupri = CPUPRI_IDLE;
    	else if (prio >= MAX_RT_PRIO)
    		cpupri = CPUPRI_NORMAL;
    	else/*prio参数是task的优先级,目前只使用在rt sched class中
    	    可以看到task的优先级越高(prio越小),对应的CPU priority越大。*/
    		cpupri = MAX_RT_PRIO - prio + 1;
    
    	return cpupri;
    }
    
    如何根据task优先级查找task能够放置哪些CPU上
    static inline int __cpupri_find(struct cpupri *cp, struct task_struct *p,
    				struct cpumask *lowest_mask, int idx)
    {   /*idx对应CPU priority,可以获取cpupri_vec结构体信息,里面包含了cpumask信息*/
    	struct cpupri_vec *vec  = &cp->pri_to_cpu[idx];
    	int skip = 0;
        /*此优先级没有被设置过,直接跳过,也就是说这个优先级没有使用过。*/
    	if (!atomic_read(&(vec)->count))
    		skip = 1;
    	/*
    	 * When looking at the vector, we need to read the counter,
    	 * do a memory barrier, then read the mask.
    	 *
    	 * Note: This is still all racey, but we can deal with it.
    	 *  Ideally, we only want to look at masks that are set.
    	 *
    	 *  If a mask is not set, then the only thing wrong is that we
    	 *  did a little more work than necessary.
    	 *
    	 *  If we read a zero count but the mask is set, because of the
    	 *  memory barriers, that can only happen when the highest prio
    	 *  task for a run queue has left the run queue, in which case,
    	 *  it will be followed by a pull. If the task we are processing
    	 *  fails to find a proper place to go, that pull request will
    	 *  pull this task if the run queue is running at a lower
    	 *  priority.
    	 */
    	smp_rmb();
    
    	/* Need to do the rmb for every iteration */
    	if (skip)
    		return 0;
        /*是否存在交集,task的cpu affinity与vec->mask*/
    	if (cpumask_any_and(p->cpus_ptr, vec->mask) >= nr_cpu_ids)
    		return 0;
        /*lowest_mask初始化一般为当前cpu的mask*/
    	if (lowest_mask) {
    	    /*task的cpu affinity与vec->mask交集赋值给lowest_mask*/
    		cpumask_and(lowest_mask, p->cpus_ptr, vec->mask);
    
    		/*
    		 * We have to ensure that we have at least one bit
    		 * still set in the array, since the map could have
    		 * been concurrently emptied between the first and
    		 * second reads of vec->mask.  If we hit this
    		 * condition, simply act as though we never hit this
    		 * priority level and continue on.
    		 */
    		if (cpumask_empty(lowest_mask))
    			return 0;
    	}
    
    	return 1;
    }
    /*使用在非ASYM系统中,即每个CPU都有一样的计算能力*/
    int cpupri_find(struct cpupri *cp, struct task_struct *p,
    		struct cpumask *lowest_mask)
    {
    	return cpupri_find_fitness(cp, p, lowest_mask, NULL);
    }
    /*使用在ASYM系统中,比如ARM分big/little,即存在不同计算能力的cluster。所以在选择cpumask的时候
    需要考虑当前task能否放置到此mask中吗?*/
    /**
     * cpupri_find_fitness - find the best (lowest-pri) CPU in the system
     * @cp: The cpupri context
     * @p: The task
     * @lowest_mask: A mask to fill in with selected CPUs (or NULL)
     * @fitness_fn: A pointer to a function to do custom checks whether the CPU
     *              fits a specific criteria so that we only return those CPUs.
     *  * Note: This function returns the recommended CPUs as calculated during the
     * current invocation.  By the time the call returns, the CPUs may have in
     * fact changed priorities any number of times.  While not ideal, it is not
     * an issue of correctness since the normal rebalancer logic will correct
     * any discrepancies created by racing against the uncertainty of the current
     * priority configuration.
     *  * Return: (int)bool - CPUs were found
     */
    int cpupri_find_fitness(struct cpupri *cp, struct task_struct *p,
    		struct cpumask *lowest_mask,
    		bool (*fitness_fn)(struct task_struct *p, int cpu))
    {   /*task优先级转化为CPU priority*/
    	int task_pri = convert_prio(p->prio);
    	int idx, cpu;
    
    	BUG_ON(task_pri >= CPUPRI_NR_PRIORITIES);
        /*task对应的CPU priority为task_pri,所以只查找比task_pri优先级小的CPU priority对应的cpumask*/
    	for (idx = 0; idx < task_pri; idx++) {
            /*查找符合要求的CPU priority对应的cpumask,存储在lowest_mask中*/
    		if (!__cpupri_find(cp, p, lowest_mask, idx))
    			continue;
    
    		if (!lowest_mask || !fitness_fn)
    			return 1;
    
    		/* Ensure the capacity of the CPUs fit the task */
    		for_each_cpu(cpu, lowest_mask) {
    		    /*查找到的lowest_mask能够放置task p,放置不下,则从mask中clear。*/
    			if (!fitness_fn(p, cpu))
    				cpumask_clear_cpu(cpu, lowest_mask);
    		}
    
    		/*
    		 * If no CPU at the current priority can fit the task
    		 * continue looking
    		 */
    		if (cpumask_empty(lowest_mask))
    			continue;
    
    		return 1;
    	}
    
    	/*
    	 * If we failed to find a fitting lowest_mask, kick off a new search
    	 * but without taking into account any fitness criteria this time.
    	 *
    	 * This rule favours honouring priority over fitting the task in the
    	 * correct CPU (Capacity Awareness being the only user now).
    	 * The idea is that if a higher priority task can run, then it should
    	 * run even if this ends up being on unfitting CPU.
    	 *
    	 * The cost of this trade-off is not entirely clear and will probably
    	 * be good for some workloads and bad for others.
    	 *
    	 * The main idea here is that if some CPUs were overcommitted, we try
    	 * to spread which is what the scheduler traditionally did. Sys admins
    	 * must do proper RT planning to avoid overloading the system if they
    	 * really care.
    	 */ /*存在的可能性,就是lowest_mask全部放置不下task p怎么办?只能又重新查找了,这里可以优化,不需要重新调用cpupri_find函数的。*/
    	if (fitness_fn)
    		return cpupri_find(cp, p, lowest_mask);
    
    	return 0;
    }
    /*其中fitness_fn函数指向如下:*/
    /*
     * Verify the fitness of task @p to run on @cpu taking into account the uclamp
     * settings.
     *
     * This check is only important for heterogeneous systems where uclamp_min value
     * is higher than the capacity of a @cpu. For non-heterogeneous system this
     * function will always return true.
     *
     * The function will return true if the capacity of the @cpu is >= the
     * uclamp_min and false otherwise.
     *
     * Note that uclamp_min will be clamped to uclamp_max if uclamp_min
     * > uclamp_max.
     */
    static inline bool rt_task_fits_capacity(struct task_struct *p, int cpu)
    {
    	unsigned int min_cap;
    	unsigned int max_cap;
    	unsigned int cpu_cap;
    
    	/* Only heterogeneous systems can benefit from this check */
    	if (!static_branch_unlikely(&sched_asym_cpucapacity))
    		return true;
    
    	min_cap = uclamp_eff_value(p, UCLAMP_MIN);
    	max_cap = uclamp_eff_value(p, UCLAMP_MAX);
    
    	cpu_cap = capacity_orig_of(cpu);
        /*即CPU本身的capacity能够满足task本身对CPU capacity(性能)的需求*/
    	return cpu_cap >= min(min_cap, max_cap);
    }
    

    使用场合在:

    • task选择哪个CPU运行的时候
    • load balance的时候(push操作的时候)
    如何更新CPU priority结构体信息
    /**
     * cpupri_set - update the CPU priority setting
     * @cp: The cpupri context
     * @cpu: The target CPU
     * @newpri: The priority (INVALID-RT99) to assign to this CPU
     *  * Note: Assumes cpu_rq(cpu)->lock is locked
     *  * Returns: (void)
     *//*更新 CPU priority信息。即cpu添加到newprio对应的cpu priority的cpumask中*/
    void cpupri_set(struct cpupri *cp, int cpu, int newpri)
    {   /*此CPU对应的CPU priority,并且需要将此CPU从这个优先级对应的mask中清除掉。*/
    	int *currpri = &cp->cpu_to_pri[cpu];
    	int oldpri = *currpri;
    	int do_mb = 0;
    
    	newpri = convert_prio(newpri);
    
    	BUG_ON(newpri >= CPUPRI_NR_PRIORITIES);
        /*相同就无需任何操作了。*/
    	if (newpri == oldpri)
    		return;
       
    	/*
    	 * If the CPU was currently mapped to a different value, we
    	 * need to map it to the new value then remove the old value.
    	 * Note, we must add the new value first, otherwise we risk the
    	 * cpu being missed by the priority loop in cpupri_find.
    	 */
    	if (likely(newpri != CPUPRI_INVALID)) {
    		struct cpupri_vec *vec = &cp->pri_to_cpu[newpri];
    
    		cpumask_set_cpu(cpu, vec->mask);
    		/*
    		 * When adding a new vector, we update the mask first,
    		 * do a write memory barrier, and then update the count, to
    		 * make sure the vector is visible when count is set.
    		 */
    		smp_mb__before_atomic();
    		atomic_inc(&(vec)->count);
    		do_mb = 1;
    	}
    	if (likely(oldpri != CPUPRI_INVALID)) {
    		struct cpupri_vec *vec  = &cp->pri_to_cpu[oldpri];
    
    		/*
    		 * Because the order of modification of the vec->count
    		 * is important, we must make sure that the update
    		 * of the new prio is seen before we decrement the
    		 * old prio. This makes sure that the loop sees
    		 * one or the other when we raise the priority of
    		 * the run queue. We don't care about when we lower the
    		 * priority, as that will trigger an rt pull anyway.
    		 *
    		 * We only need to do a memory barrier if we updated
    		 * the new priority vec.
    		 */
    		if (do_mb)
    			smp_mb__after_atomic();
    
    		/*
    		 * When removing from the vector, we decrement the counter first
    		 * do a memory barrier and then clear the mask.
    		 */
    		atomic_dec(&(vec)->count);
    		smp_mb__after_atomic();
    		cpumask_clear_cpu(cpu, vec->mask);
    	}
    
    	*currpri = newpri;
    }
    

    使用场合:

    • task入队
    • task出队
    • rq online
    • rq offline

    都可能会改变对应CPU priority的数值。

    展开全文
  • Android Priority Job Queue

    2016-06-16 17:47:44
    Android Priority Job Queue
  • 线程优先级 Priority

    2019-04-16 21:15:19
    你可以使用常量,如MIN_PRIORITY,MAX_PRIORITY,NORM_PRIORITY来设定优先级。 优先级的取值 Java线程的优先级是一个整数,其取值范围是1 (Thread.MIN_PRIORITY ) - 10 (Thread.MAX_PRIORITY )。 ...

    此文前半部分为转载文章。转载自:https://www.cnblogs.com/duanxz/p/5226109.html

    后半部分的集结代码为自敲代码。

    Java线程可以有优先级的设定,高优先级的线程比低优先级的线程有更高的几率得到执行(不完全正确,请参考下面的“线程优先级的问题“)。

    1. 记住当线程的优先级没有指定时,所有线程都携带普通优先级。
    2. 优先级可以用从1到10的范围指定。10表示最高优先级,1表示最低优先级,5是普通优先级。
    3. 记住优先级最高的线程在执行时被给予优先。但是不能保证线程在启动时就进入运行状态。
    4. 与在线程池中等待运行机会的线程相比,当前正在运行的线程可能总是拥有更高的优先级。
    5. 由调度程序决定哪一个线程被执行。
    6. t.setPriority()用来设定线程的优先级。
    7. 记住在线程开始方法被调用之前,线程的优先级应该被设定。
    8. 你可以使用常量,如MIN_PRIORITY,MAX_PRIORITY,NORM_PRIORITY来设定优先级。

    优先级的取值

    Java线程的优先级是一个整数,其取值范围是1 (Thread.MIN_PRIORITY ) - 10 (Thread.MAX_PRIORITY )。

    Thread源代码里对NORM_PRIORITY (数值为5) 的注释是“线程默认的优先级”

    public static final int MIN_PRIORITY = 1;
    public static final int NORM_PRIORITY = 5;
    public static final int MAX_PRIORITY = 10;

    其实不然。默认的优先级是父线程的优先级。在init方法里,

    Thread parent = currentThread();  
    this.priority = parent.getPriority();  

     或许这么解释是因为Java程序的主线程(main方法)的优先级默认是为NORM_PRIORITY,这样不主动设定优先级的,后续创建的线程的优先级也都是NORM_PRIORITY了。

    public static void main(String[] args) {  
        System.out.println(Thread.currentThread().getPriority());  
    }  

    其执行结果是5。

    设置优先级

    可以通过setPriority方法(final的,不能被子类重载)更改优先级。优先级不能超出1-10的取值范围,否则抛出IllegalArgumentException。另外如果该线程已经属于一个线程组(ThreadGroup),该线程的优先级不能超过该线程组的优先级:

    public final void setPriority(int i)
        {
            checkAccess();
            if(i > 10 || i < 1)
                throw new IllegalArgumentException();
            ThreadGroup threadgroup;
            if((threadgroup = getThreadGroup()) != null)
            {
                if(i > threadgroup.getMaxPriority())
                    i = threadgroup.getMaxPriority();
                setPriority0(priority = i);
            }
        }

     

     其中setPriority0是一个本地方法。

    private native void setPriority0(int i);

    线程组的最大优先级

    我们可以设定线程组的最大优先级,当创建属于该线程组的线程时该线程的优先级不能超过这个数。

    线程组最大优先级的设定:

    • 系统线程组的最大优先级默认为Thread.MAX_PRIORITY
    • 创建线程组的时候其最大优先级默认为父线程组(如果未指定父线程组,则其父线程组默认为当前线程所属线程组)的最大优先级
    • 可以通过setMaxPriority更改最大优先级,但无法超过父线程组的最大优先级

    setMaxPriority的问题:

    • 该方法只能更改本线程组及其子线程组(递归)的最大优先级。
    • 但不能影响已经创建的直接或间接属于该线程组的线程的优先级,也就是说,即使目前有一个子线程的优先级比新设定的线程组优先级大,也不会更改该子线程的优先级。只有当试图改变子线程的优先级或者创建新的子线程的时候,线程组的最大优先级才起作用。

    线程优先级的问题

    以下内容摘抄、翻译自JAVAMEX -> Java threading introduction -> Thread priorioties

    对于线程优先级,我们需要注意:

    * Thread.setPriority()可能根本不做任何事情,这跟你的操作系统和虚拟机版本有关
    * 线程优先级对于不同的线程调度器可能有不同的含义,可能并不是你直观的推测。特别地,优先级并不一定是指CPU的分享。在UNIX系统,优先级或多或少可以认为是CPU的分配,但Windows不是这样
    * 线程的优先级通常是全局的和局部的优先级设定的组合。Java的setPriority()方法只应用于局部的优先级。换句话说,你不能在整个可能的范围 内设定优先级。(这通常是一种保护的方式,你大概不希望鼠标指针的线程或者处理音频数据的线程被其它随机的用户线程所抢占)
    * 不同的系统有不同的线程优先级的取值范围,但是Java定义了10个级别(1-10)。这样就有可能出现几个线程在一个操作系统里有不同的优先级,在另外一个操作系统里却有相同的优先级(并因此可能有意想不到的行为)
    * 操作系统可能(并通常这么做)根据线程的优先级给线程添加一些专有的行为(例如”only give a quantum boost if the priority is below X“)。这里再重复一次,优先级的定义有部分在不同系统间有差别。
    * 大多数操作系统的线程调度器实际上执行的是在战略的角度上对线程的优先级做临时操作(例如当一个线程接收到它所等待的一个事件或者I/O),通常操作系统知道最多,试图手工控制优先级可能只会干扰这个系统。
    * 你的应用程序通常不知道有哪些其它进程运行的线程,所以对于整个系统来说,变更一个线程的优先级所带来的影响是难于预测的。例如你可能发现,你有一个预期 为偶尔在后台运行的低优先级的线程几乎没有运行,原因是一个病毒监控程序在一个稍微高一点的优先级(但仍然低于普通的优先级)上运行,并且无法预计你程序 的性能,它会根据你的客户使用的防病毒程序不同而不同。
     

     你可以参考Java优先级与各操作系统优先级之间的对应关系

    实际编码注意事项

      • 不要假定高优先级的线程一定先于低优先级的线程执行,不要有逻辑依赖于线程优先级,否则可能产生意外结果

     集结测试:

    package Thread;
    
    /**
     *    只是个概率的问题
     *    优先级只是意味着获得调度的概率低。并不是绝对先调用优先级高
     *    后 调用优先级低的线程
     *1、NORM_PRIORITY 5 默认
     *2、MIN_PRIORITY  1
     *3、MAX_PRIORITY  10
     * @author Administrator
     *
     */
    
    public class Priority {
    	
    	public static void main(String[] args) {
    		System.out.println(Thread.currentThread().getPriority());
    		
    		MyPriority mp = new MyPriority();
    		//不用匿名是为了等下创建多个线程
    		Thread t1 = new Thread(mp,"adidas");
    		Thread t2 = new Thread(mp,"NIKE");
    		Thread t3 = new Thread(mp,"回力");
    		Thread t4 = new Thread(mp,"JorDan");
    		Thread t5 = new Thread(mp,"李宁");
    		Thread t6 = new Thread(mp,"puma");
    		
    		//设置优先级要在启动前
    		t1.setPriority(Thread.MAX_PRIORITY);
    		t2.setPriority(Thread.MAX_PRIORITY);
    		t3.setPriority(Thread.MAX_PRIORITY);
    		t4.setPriority(Thread.MIN_PRIORITY);
    		t5.setPriority(Thread.MIN_PRIORITY);
    		t6.setPriority(Thread.MIN_PRIORITY);
    				   	
    		t1.start();
    		t2.start();
    		t3.start();
    		t4.start();
    		t5.start();
    		t6.start();
    	}
    		
    }
    
    class MyPriority implements Runnable{
    	@Override
    	public void run() {
    		System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
    		Thread.yield();
    	}
    }
    

    结果:

    5
    adidas-->10
    NIKE-->10
    李宁-->1
    回力-->10
    puma-->1
    JorDan-->1
    

     

    展开全文
  • An Asynchronous Adaptive Priority Round-Robin Arbiter Based on Four-Phase Dual-rail Protocol
  • 西电的操作系统课设3(优先级捐赠方法解决优先级翻转问题),含源码(只放了四个需要修改的c和h文件,都是在课设2的基础上做的,课设2和3的代码均备注了修改的起末段落,且使用了不尽相同的备注)。...
  • Priority-Based Genetic Algorithm for Shortest Path Routing Problem in OSPF 主要介绍了遗传算法求解最短路径问题中的基于优先级的编码。这种编码方式可以很有效地解决图的最短路径等问题。
  • 今天要来说一下Orderd接口以及@Order、@Primary、@Priority注解这几个东西,原本只是想介绍一下@Order,但是这几个有一定的关联,因此这里一起进行介绍。这几个接口是用来排序,本文主要介绍用法,具体的比如Spring...
  • C++ priority_queue 的使用和源码详解

    千次阅读 2020-06-14 17:01:31
    priority_queue 是一个拥有权值观念的 queue,它允许加入新的元素、移除旧的元素、查看 priority_queue 中权值之最的元素等功能。priority_queue 只允许在底端加入元素,并从顶端取出元素,除此之外没有其它存取元素...
  • keyed_priority_queue-源码

    2021-05-09 21:25:24
    use keyed_priority_queue :: {KeyedPriorityQueue, Entry}; let mut queue = KeyedPriorityQueue :: new (); // Currently queue is empty assert_eq! (queue. peek (), None ); queue. push ( "Second" , 4 ); ...
  • priority_queue的用法

    千次阅读 多人点赞 2019-03-29 19:06:49
    priority_queue的用法 priority_queue本质是一个堆。 头文件是#include 关于priority_queue中元素的比较  模板申明带3个参数:priority_queue<Type, Container, Functional>,其中Type 为数据类型...
  • Spark对于Yarn priority的支持源码详解 Yarn的调度器 在Yarn中,提供了Capacity scheduler和Fair scheduler,它们都支持priority的。这里我们简单介绍下概念,不做过多的描述。 Capacity Scheduler Capacity ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 435,000
精华内容 174,000
关键字:

priority