精华内容
下载资源
问答
  • linux make 多核
    千次阅读
    2020-12-17 22:20:09

    LInux下实现多核编译,只需在给make命令加上参数-jn,n为核数据。如下示例:

    make CROSS_COMPILE=arm-arago-linux-gnueabi- ARCH=arm uImage -j4
    

    更多相关内容
  • linux SMP多核启动分析

    2021-05-11 09:33:38
    /* *We count on the initial thread going ok *Like idlers init is an unlocked kernel thread, which will *make syscalls (and thus be locked). */ kernel_thread(init, NULL, 0); /* * task[0] is meant to ...

    startup_32:

    cld

    cli

    movl $(KERNEL_DS),%eax

    mov %ax,%ds

    mov %ax,%es

    mov %ax,%fs

    mov %ax,%gs

    #ifdef

    __SMP__

    orw %bx,%bx#

    What state are we in BX=1 for SMP

    # 0 for boot

    jz2f# Initial boot

    //根据bx值指示是主cpu(bx=0)还是次cpu(bx=1)

    //然后会有不同的执行路径

    /*

    *We are

    trampolining an SMP processor

    *//这里是其他次cpu执行路径

    mov %ax,%ss

    xorl %eax,%eax# Back to 0

    mov%cx,%ax# SP low 16 bits

    movl %eax,%esp

    pushl 0#

    Clear NT

    popfl

    ljmp $(KERNEL_CS),

    $0x100000# Into C and sanity

    2://这里是主cpu的执行路径

    #endif

    lss SYMBOL_NAME(stack_start),%esp

    xorl %eax,%eax

    1:incl %eax#

    check that A20 really IS enabled

    movl %eax,0x000000# loop forever if it isn't

    cmpl %eax,0x100000

    je 1b

    /*

    * Initialize eflags.Some BIOS's leave bits like NT set.This would

    * confuse the debugger if this code is traced.

    * XXX - best to initialize before switching to

    protected mode.

    */

    pushl $0

    popfl

    /*

    * Clear BSS

    */

    xorl %eax,%eax

    movl $ SYMBOL_NAME(_edata),%edi

    movl $ SYMBOL_NAME(_end),%ecx

    subl %edi,%ecx

    cld

    rep

    stosb

    /*

    * Do the decompression, and jump to the new

    kernel..

    */

    subl $16,%esp# place for structure on the stack

    pushl %esp#

    address of structure as first arg

    call SYMBOL_NAME(decompress_kernel)

    orl%eax,%eax

    jnz3f

    xorl %ebx,%ebx

    ljmp $(KERNEL_CS),

    $0x100000

    ljmp $(KERNEL_CS), $0x100000

    这个其实就是跳到start_kernel函数。

    asmlinkage void start_kernel(void)

    {

    char * command_line;

    /*

    *This little check will move.

    */

    #ifdef __SMP__

    static int

    first_cpu=1;

    //这个不是函数局部变量,是函数静态变量,主cpu执行这个函数时复位为1,其他cpu为0,因为主cpu总是第一个执行这个函数的。

    if(!first_cpu)

    start_secondary();

    //对于

    first_cpu=0;

    #endif

    /*

    * Interrupts are still

    disabled. Do necessary setups, then

    * enable them

    */

    setup_arch(&command_line,

    &memory_start, &memory_end);

    memory_start =

    paging_init(memory_start,memory_end);

    trap_init();

    init_IRQ();

    sched_init();

    time_init();

    parse_options(command_line);

    #ifdef CONFIG_MODULES

    init_modules();

    #endif

    #ifdef CONFIG_PROFILE

    if (!prof_shift)

    #ifdef CONFIG_PROFILE_SHIFT

    prof_shift =

    CONFIG_PROFILE_SHIFT;

    #else

    prof_shift = 2;

    #endif

    #endif

    if (prof_shift) {

    prof_buffer =

    (unsigned int *) memory_start;

    /* only text is

    profiled */

    prof_len = (unsigned

    long) &_etext - (unsigned long) &_stext;

    prof_len >>=

    prof_shift;

    memory_start +=

    prof_len * sizeof(unsigned int);

    }

    memory_start =

    console_init(memory_start,memory_end);

    #ifdef CONFIG_PCI

    memory_start =

    pci_init(memory_start,memory_end);

    #endif

    memory_start =

    kmalloc_init(memory_start,memory_end);

    sti();

    calibrate_delay();

    memory_start =

    inode_init(memory_start,memory_end);

    memory_start = file_table_init(memory_start,memory_end);

    memory_start =

    name_cache_init(memory_start,memory_end);

    #ifdef CONFIG_BLK_DEV_INITRD

    if (initrd_start

    && initrd_start < memory_start) {

    printk(KERN_CRIT

    "initrd overwritten (0x%08lx < 0x%08lx) - "

    "disabling it.\n",initrd_start,memory_start);

    initrd_start = 0;

    }

    #endif

    mem_init(memory_start,memory_end);

    buffer_init();

    sock_init();

    #if defined(CONFIG_SYSVIPC) || defined(CONFIG_KERNELD)

    ipc_init();

    #endif

    dquot_init();

    arch_syms_export();

    sti();

    check_bugs();

    printk(linux_banner);

    #ifdef __SMP__

    smp_init();

    #endif

    sysctl_init();

    /*

    *We

    count on the initial thread going ok

    *Like

    idlers init is an unlocked kernel thread, which will

    *make

    syscalls (and thus be locked).

    */

    kernel_thread(init,

    NULL, 0);

    /*

    * task[0] is meant to be

    used as an "idle" task: it may not sleep, but

    * it might do some general

    things like count free pages or it could be

    * used to implement a

    reasonable LRU algorithm for the paging routines:

    * anything that can be

    useful, but shouldn't take time from the real

    * processes.

    *

    * Right now task[0] just

    does a infinite idle loop.

    */

    cpu_idle(NULL);

    }

    asmlinkage void start_secondary(void)

    {

    trap_init();

    init_IRQ();

    //初始化自己的irq

    smp_callin();

    //这个等待主cpu给大家发送开始信号

    cpu_idle(NULL);

    //这个是ide进程。

    }

    void smp_callin(void)

    {

    extern void

    calibrate_delay(void);

    int

    cpuid=GET_APIC_ID(apic_read(APIC_ID));

    unsigned long l;

    /*

    *Activate

    our APIC

    */

    SMP_PRINTK(("CALLIN

    %d\n",smp_processor_id()));

    l=apic_read(APIC_SPIV);

    l|=(1<<8);/*

    Enable */

    apic_write(APIC_SPIV,l);

    sti();

    /*

    *Get

    our bogomips.

    */

    calibrate_delay();

    /*

    *Save

    our processor parameters

    */

    smp_store_cpu_info(cpuid);

    /*

    *Allow

    the master to continue.

    */

    set_bit(cpuid, (unsigned

    long *)&cpu_callin_map[0]);

    /*

    *Until

    we are ready for SMP scheduling

    */

    load_ldt(0);

    /*printk("Testing

    faulting...\n");

    *(long *)0=1; OOPS... */

    local_flush_tlb();

    while(!smp_commenced);

    //这个可以看成是自旋锁,等待主cpu发smp_commenced信号即开始信号。

    if (cpu_number_map[cpuid]

    == -1)

    while(1);

    local_flush_tlb();

    SMP_PRINTK(("Commenced..\n"));

    load_TR(cpu_number_map[cpuid]);

    /*while(1);*/

    }

    int cpu_idle(void *unused)

    {

    for(;;)

    idle();

    }

    主cpu给各次cpu发开始信号是在init函数中调用smp_begin函数:

    static void smp_begin(){

    smp_threads_ready=1;

    smp_commence();

    //这个会通过IPI给各个次cpu发送相关中断来通信

    }

    每个cpu有一个current指针。

    刚开始的时候由主cpu赋值为init_task;

    在主cpu调用 sched_init赋值。

    void sched_init(void)

    {

    /*

    *We

    have to do a little magic to get the first

    *process

    right in SMP mode.

    */

    int

    cpu=smp_processor_id();//这个为0,因为是主cpu才调用。

    #ifndef __SMP__

    current_set[cpu]=&init_task;

    #else

    init_task.processor=cpu;

    //这个是将init_task标志为主cpu在运行。

    for(cpu = 0; cpu <

    NR_CPUS; cpu++)

    current_set[cpu] =

    &init_task;

    #endif

    init_bh(TIMER_BH,

    timer_bh);

    init_bh(TQUEUE_BH,

    tqueue_bh);

    init_bh(IMMEDIATE_BH,

    immediate_bh);

    }

    同时这些还会在 smp_init丰富。

    static void smp_init(void)

    {

    int i, j;

    smp_boot_cpus();

    /*

    *Create

    the slave init tasks as sharing pid 0.

    *

    *This

    should only happen if we have virtual CPU numbers

    *higher

    than 0.

    */

    for (i=1;

    i

    {

    struct task_struct

    *n, *p;

    j =

    cpu_logical_map[i];

    /*

    *We use

    kernel_thread for the idlers which are

    *unlocked

    tasks running in kernel space.

    */

    kernel_thread(cpu_idle,

    NULL, CLONE_PID);

    //这个其实就是创建线程然后这个线程体现在task[i]上了,因为创建的时候的task_struct就是从task[i]取的。

    /*

    *Don't

    assume linear processor numbering

    */

    current_set[j]=task[i];

    current_set[j]->processor=j;

    cli();

    n =

    task[i]->next_run;

    p =

    task[i]->prev_run;

    nr_running--;

    n->prev_run = p;

    p->next_run = n;

    task[i]->next_run

    = task[i]->prev_run = task[i];

    sti();

    }

    }

    上面执行完后就给每个cpu加了一个idle任务。

    然后kernel_thread(init, NULL, 0)创建的init任务。

    //每个cpu在时间中断时都可能调用这个共同的函数。

    asmlinkage void schedule(void)

    {

    int c;

    struct task_struct * p;

    struct task_struct *

    prev, * next;

    unsigned long timeout =

    0;

    int this_cpu=smp_processor_id();

    //获取cpu_id;

    /* check alarm, wake up any interruptible tasks that have got a

    signal */

    if (intr_count)

    goto

    scheduling_in_interrupt;

    if (bh_active &

    bh_mask) {

    intr_count = 1;

    do_bottom_half();

    intr_count = 0;

    }

    run_task_queue(&tq_scheduler);

    need_resched = 0;

    prev = current;

    cli();

    /* move an exhausted RR

    process to be last.. */

    if (!prev->counter

    && prev->policy == SCHED_RR) {

    prev->counter =

    prev->priority;

    move_last_runqueue(prev);

    }

    switch (prev->state) {

    case

    TASK_INTERRUPTIBLE:

    if

    (prev->signal & ~prev->blocked)

    goto

    makerunnable;

    timeout =

    prev->timeout;

    if (timeout

    && (timeout <= jiffies)) {

    prev->timeout

    = 0;

    timeout = 0;

    makerunnable:

    prev->state

    = TASK_RUNNING;

    break;

    }

    default:

    del_from_runqueue(prev);

    case TASK_RUNNING:

    }

    p =

    init_task.next_run;

    //获取进程双向链表的一个节点。

    sti();

    #ifdef __SMP__

    /*

    *This

    is safe as we do not permit re-entry of schedule()

    */

    prev->processor =

    NO_PROC_ID;

    #define idle_task (task[cpu_number_map[this_cpu]])

    #else

    #define idle_task (&init_task)

    #endif

    /*

    * Note! there may appear

    new tasks on the run-queue during this, as

    * interrupts are enabled.

    However, they will be put on front of the

    * list, so our list

    starting at "p" is essentially fixed.

    */

    /* this is the scheduler proper: */

    c = -1000;

    next = idle_task;

    while (p !=

    &init_task) {

    //p初始值为init_task.next_run

    //当回到init_task时说明已经查找为所有的了。

    int weight =

    goodness(p, prev, this_cpu);

    if (weight > c)

    c = weight, next =

    p;

    p = p->next_run;

    }

    //这个是查找所有的task,找出最合适的task来调度。

    /* if all runnable processes

    have "counter == 0", re-calculate counters */

    if (!c) {

    for_each_task(p)

    p->counter =

    (p->counter >> 1) + p->priority;

    }

    #ifdef __SMP__

    /*

    *Allocate

    process to CPU

    */

    next->processor = this_cpu;

    //将这个将要被执行的processor标识为这个cpu

    next->last_processor = this_cpu;

    #endif

    #ifdef __SMP_PROF__

    /* mark processor running

    an idle thread */

    if (0==next->pid)

    set_bit(this_cpu,&smp_idle_map);

    else

    clear_bit(this_cpu,&smp_idle_map);

    #endif

    if (prev != next) {

    struct timer_list

    timer;

    kstat.context_swtch++;

    if (timeout) {

    init_timer(&timer);

    timer.expires =

    timeout;

    timer.data =

    (unsigned long) prev;

    timer.function =

    process_timeout;

    add_timer(&timer);

    }

    get_mmu_context(next);

    switch_to(prev,next);

    if (timeout)

    del_timer(&timer);

    }

    return;

    scheduling_in_interrupt:

    printk("Aiee:

    scheduling in interrupt %p\n",

    __builtin_return_address(0));

    }

    上面需要注意的是current变量,在单核中肯定就是一个变量,在多核中肯定是各个cpu有自己的current:

    其定义如下:

    #define current (0+current_set[smp_processor_id()]

    在smp中current是current_set数组中的一个元素,是指具体一个cpu的当前进程。

    从上面可以看出一个cpu是从全局task找一个task来运行,每个cpu有一个idle_task,这个task的编号是固定的。

    所有的task可以通过init_task来找到,因为创建新进程(内核线程)的时候,会将新建的挂到链表上。

    而init_task是静态挂在这上面的。

    附上task_struct:

    struct task_struct {

    /* these are hardcoded - don't touch */

    volatile long state;/* -1 unrunnable, 0 runnable, >0 stopped

    */

    long counter;

    long priority;

    unsigned long signal;

    unsigned long blocked;/* bitmap of masked signals */

    unsigned long flags;/* per process flags, defined below */

    int errno;

    long debugreg[8];/* Hardware debugging registers */

    struct exec_domain

    *exec_domain;

    /* various fields */

    struct linux_binfmt

    *binfmt;

    struct task_struct

    *next_task, *prev_task;

    struct task_struct

    *next_run,*prev_run;

    unsigned long

    saved_kernel_stack;

    unsigned long

    kernel_stack_page;

    int exit_code,

    exit_signal;

    /* ??? */

    unsigned long

    personality;

    int dumpable:1;

    int did_exec:1;

    /* shouldn't this be

    pid_t? */

    int pid;

    int pgrp;

    int tty_old_pgrp;

    int session;

    /* boolean value for

    session group leader */

    int leader;

    intgroups[NGROUPS];

    /*

    * pointers to (original) parent process,

    youngest child, younger sibling,

    * older sibling, respectively.(p->father can be replaced with

    * p->p_pptr->pid)

    */

    struct task_struct

    *p_opptr, *p_pptr, *p_cptr, *p_ysptr, *p_osptr;

    struct wait_queue

    *wait_chldexit;/* for wait4() */

    unsigned short

    uid,euid,suid,fsuid;

    unsigned short gid,egid,sgid,fsgid;

    unsigned long timeout,

    policy, rt_priority;

    unsigned long

    it_real_value, it_prof_value, it_virt_value;

    unsigned long

    it_real_incr, it_prof_incr, it_virt_incr;

    struct timer_list

    real_timer;

    long utime, stime,

    cutime, cstime, start_time;

    /* mm fault and swap info: this can arguably be seen as either

    mm-specific or thread-specific */

    unsigned long min_flt,

    maj_flt, nswap, cmin_flt, cmaj_flt, cnswap;

    int swappable:1;

    unsigned long

    swap_address;

    unsigned long

    old_maj_flt;/* old value of maj_flt */

    unsigned long dec_flt;/* page fault count of the last time */

    unsigned long swap_cnt;/* number of pages to swap on next pass */

    /* limits */

    struct rlimit

    rlim[RLIM_NLIMITS];

    unsigned short used_math;

    char comm[16];

    /* file system info */

    int link_count;

    struct tty_struct *tty;

    /* NULL if no tty */

    /* ipc stuff */

    struct sem_undo *semundo;

    struct sem_queue

    *semsleeping;

    /* ldt for this task - used by Wine.If NULL, default_ldt is used */

    struct desc_struct *ldt;

    /* tss for this task */

    struct thread_struct tss;

    /* filesystem information */

    struct fs_struct *fs;

    /* open file information */

    struct files_struct

    *files;

    /* memory management info */

    struct mm_struct *mm;

    /* signal handlers */

    struct signal_struct

    *sig;

    #ifdef __SMP__

    int processor;

    int last_processor;

    int lock_depth;/* Lock depth. We can context switch in and

    out of holding a syscall kernel lock... */

    #endif

    };

    故这个p = init_task.next_run;

    p可以获取到所有在就绪状态的task;

    展开全文
  • [TOC]OCTEON MIPS C7100 SMP linux多核启动由u-boot和linux协同完成。本文所用u-boot和linux代码库分别是u-boot-octeon-sdk3.1和linux-octeon-sdk3.1。任何MIPS Core都是从系统的虚拟地址0xbfc00000启动的,其对应...

    66b52468c121889b900d4956032f1009.png

    8种机械键盘轴体对比

    本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?

    [TOC]

    OCTEON MIPS C7100 SMP linux的多核启动由u-boot和linux协同完成。本文所用u-boot和linux代码库分别是u-boot-octeon-sdk3.1和linux-octeon-sdk3.1。

    任何MIPS Core都是从系统的虚拟地址0xbfc00000启动的,其对应的物理地址为0x1FC00000。因为上述地址处于kseg1中,所以此时系统不需要TLB映射就能够运行(这段空间通过去掉最高的三位来获得物理地址)。

    Cavium CPU根据型号不同,一个CPU里面可能集成了多个Core。这些Core里面,在上电时,只有core 0(一般称之为主核,其它核称为从核)会从reset状态跳转到物理地址0x1FC00000(我们的flash起始地址会映射成这个值),开始执行相关的一系列初始化代码,如内存、外设等等。而另外一些核则仍处于reset状态,只有core 0主动去唤醒它们时,从核才有可能开始正常运转。

    2. u-boot阶段

    5f5bda6f5be1c8fc3d0986b9ff19f331.png

    (1)上电后core0从跳转到物理地址 0x1fc00000,即flash 0地址开始运行 u-boot,初始化TLB,memory;

    (2)core0在board_init_f阶段调用octeon_boot_bus_moveable_init将SecondaryCoreInit( 在 u-boot-octeon-sdk3.1/ arch/mips/cpu/octeon/start.S中定义 )代码段拷贝到bootbus模块的Local Memory Region 0(后面简称BBLMR0),并将BBLMR0的地址映射到物理地址0x1fc0 0000(写MIO_BOOT_LOC_CFG寄存器);

    (3)core0在board_init_r(DDR已经初始化,u-boot完成reolcation)阶段调用octeon_enable_all_cores函数reset从核;

    (4)从核reset,跳转到物理地址0x1fc00000,也即 BBLMR0 执行 SecondaryCoreInit,读取boot vector table(第一次读取)(地址BOOT_VECTOR_BASE等于虚拟地址0x80000800,即物理地址0x800),此时 BOOT_VECTOR_BASE还没有被初始化,从核将sleep等待NMI 唤醒 中断;

    (5)core0在main_loop运行bootoctlinux命令,调用octeon_setup_boot_desc_block和octeon_setup_boot_vector 初始化各核(包括core0)的boot_desc和boot_vect;将 boot_vect的 app_start_func_addr指向 start_linux函数,code_addr指向InitTLBStart函数(注:这里 InitTLBStart被转换成物理地址,从核刚刚从reset释放到时候才能寻址,因为这个时候还没有初始化TLB,从核只能访问kseg0地址段 )。 主核(即first_core,这里是core0)的 boot_desc的flag置BOOT_FLAG_INIT_CORE,后面主核在启动linux的时候(函数start_linux)将设置寄存器a2为1,主核kernel启动时发现a2被置位将执行linux初始化,并唤醒从核。

    /* Here we need to figure out the physical address of the

    * InitTLBStart function.

    */

    boot_vect[core].code_addr =

    MAKE_XKPHYS(uboot_tlb_ptr_to_phys(&InitTLBStart));

    debug("Setting core %d code_addr address(0x%p) to: 0x%llxn",

    core, &(boot_vect[core].code_addr),

    boot_vect[core].code_addr);

    打开debug输出,内容是Setting core 3 code_addr address(0x80000860) to: 0x800000010f0006d0,可见reloc code_addr address是 0x800000010f0006d0,就是core0的u-boot被从flash relocate到高端地址之后 InitTLBStart的物理地址; SecondaryCoreInit在enable 64bit寻址之后,跳转到虚拟地址 0x800000010f0006d0也就是 InitTLBStart等 物理地址0x 10f0006d0开始执行 InitTLBStart。

    (6)core0给从核发送NMI中断;

    (7)从核跳转到 物理地址0x1fc00000,也即 BBLMR0 执行 SecondaryCoreInit, 读取boot vector table(第二次读取),得到code_addr,跳转到 InitTLBStart,初始化TLB;

    (8)从核清MNI中断,跳转到init_secondary读取 boot vector table(第三次读取),得到app_start_func_addr,跳转到 start_linux,调用asm_launch_linux_entry_point函数启动linux,跳转到 kernel_entry;

    (9)core0在发生MNI中断唤醒从核之后,直接调用 app_start_func_addr也就是 start_linux启动linux,跳转到 kernel_entry。

    3. linux阶段

    40176f458f00c5c6d2ed8277de5d23a8.png

    (1)主核core0 启动linux的入口是 kernel_entry(在arch/mips/kerenl/head.S中定义),跳转到kernel_entry_setup(在archmipsincludeasmmach-cavium-octeonkernel-entry-init.h定义),因为BootLoader将主核core0的寄存器a2设置为1,所以跳转到octeon_main_processor,继而跳转到start_kernel继续启动linux;

    (2)从核启动linux的入口也是kernel_entry,因为BootLoader将从核的寄存器a2设置为0,于是进入octeon_spin_wait_boot等待主核core0唤醒;

    (3)主核core0执行start_kernel,调用boot_cpu_init,设置core0点cpu状态为online(可被 调度 ),active(可被 迁移 ), present( 被内核接管 ) , possible(系统存在,但没有被内核接管);

    (4)主核 core0调用setup_arch进行mips体系结构相关初始化,与SMP相关的有:prom_init调用octeon_setup_smp注册octeon_smp_ops结构体,赋值给全局变量struct plat_smp_ops *mp_ops,是多核启动的操作函数集;plat_smp_setup调用 plat_smp_ops函数集octeon_smp_ops 的octeon_smp_setup根据coremask参数设置可以被启动点从核的各cpu状态为 present( 被内核接管 )和 possible(系统存在,但没有被内核接管),设置各从核cpu点logic map。

    (5)主核 core0在kernel_init线程执行smp_prepare_cpus,调用octeon_smp_ops 的octeon_prepare_cpus初始化mailbox并申请mailbox中断;

    (6)主核 core0执行smp_init,调用idle_threads_init初始化idle线程,然后调用cpu,最终调用octeon_smp_ops的octeon_boot_secondary,将 octeon_processor_sp和octeon_processor_gp指向idle线程的stack,将octeon_processor_sp赋值为待启动从核点逻辑core id;

    (7)从核 octeon_spin_wait_boot检测到 octeon_processor_sp和自己的core id匹配了,就跳出 octeon_spin_wait_boot,执行smp_bootstrap,调用start_secondary,进而调用 octeon_smp_ops 的octeon_init_secondary和octeon_smp_finish;

    (8)从核执行cpu_startup_entry进入idle loop。

    4. 参考文档《 see mips run 》

    《 Cavium多核系统地址空间布局及启动.doc 》,网络下载,文档内容不全,缺多核启动代码部分。

    Bootloader_Details_Class_Part1_R1.pptx

    Bootloader_Details_Class_Part2_R1.ppt

    Bootloader_Details_Class_Part3_R1.ppt

    Bootloader_Reference_Information_R1.pdf

    展开全文
  • linux下使用多核进行编译

    千次阅读 2018-06-08 15:36:32
    命令语法:make -j [Num]make是编译命令,-j是告诉处理器同时处理几个任务,[Num]表示使用几个核心进行编译make -j 不带参数就是使用所有核心进行编译make -j 2参数2就是表示使用两个核心进行编译...

    命令语法:

    make -j [Num]

    make是编译命令,-j是告诉处理器同时处理几个任务,[Num]表示使用几个核心进行编译

    make -j  

    不带参数就是使用所有核心进行编译

    make -j 2

    参数2就是表示使用两个核心进行编译


    展开全文
  • linux多线程demo

    2021-02-18 09:44:44
    linux多线程demo 使用cmake编译
  • 多核处理器Linux的进程绑定处理器核运行名词CPU affinity:中文称作“CPU亲和力”,是指在CMP架构下,能够将一个或多个进程绑定到一个或多个处理器上运行。一、Linux代码中绑定多核运行1、如果自己写代码,要把进程...
  • linux多核处理下提高编译速度 make -j

    万次阅读 2015-12-15 09:32:58
    Linux开源程序编译往往会需要较长时间,多核处理器的应用可以大大缩短编译所需要的时间。   默认情况下,make并没有将多核处理器的性能发挥到极限。相反,它只使用了其中一个核心。   make的-j参数可以使make进行...
  • 总结:Linux下安装单机并行lammps○.机器配置:1.处理器:Intel XEON × 22.主板:Intel S5500BC3.内存:金士顿4G × 64.操作系统:Redhat Enterprise 5.3 x86_64一.下载需要的源文件fftw-2.1.5.tar.gzmpich2-...
  • 说明:本篇章算是性能优化 一 make -j Linux开源程序编译往往会需要较长时间,多核处理器的应用可以大大缩短编译所需要的时间 默认情况下,make并没有将多核处理器的性能发挥到极限,相反它只使用了其中一个核心(不...
  • linux内核配置make-menuconfig菜单详解.doc
  • linuxmake用法

    2021-12-26 20:10:18
    1.查看make的帮助,输入如下命令: make -h 显示如下: Usage: make [options] [target] ... Options: -b, -m Ignored for compatibility. -B, --always-make Unconditionally make all targets. -C ...
  • Linux之编译make常识

    2021-04-14 21:59:31
    在使用make进行编译时,若只执行make指令则效率较低,若用make -j后面跟一个数值,比如make -j8,make -j12等则可以提高编译效率。 make -j命令后面跟着线程数,12表示这个命令使用12线路去执行编译。 假设我们的...
  • coolshell最新的文章《性能调优攻略》在“多核CPU调优”章节,提到“我们不能任由操作系统负载均衡,因为我们自己更了解自己的程序,所以,我们可以手动地为其分配CPU核,而不会过多地占用CPU0,或是让我们关键进程...
  • 源码的安装一般由3个步骤组成:配置(configure)、编译(make)、安装(make install)。安装成功的源码就是所谓的可执行文件,在你不需要的时候,也是可以删除/卸载(remove/uninstall)的。下面就逐个进行分析: ...
  • 目录获取最大可用线程数自动以最大线程数编译makecmake效果 系统:Debian 获取最大可用线程数 ...make -j $(nproc) cmake sudo cmake --build . --target all -- -j $(nproc) 效果 所用app:PiHelper ...
  • linux内核配置makemenuconfig菜单详解.pdf
  • linux内核配置make_menuconfig菜单详解.docx
  • linux编译】make -j 参数简介

    千次阅读 2020-08-18 17:34:27
    Linux编译程序的时候,IO往往不是瓶颈,那CPU就应该是一个影响编译速度的重要因素了。 用make -j带一个参数,可以把项目在进行并行编译,比如在一台双核的机器上,完全可以用make -j4,让make最多允许4个编译命令...
  • Linux编译时make -j# 应该开多少个线程

    千次阅读 2020-04-08 17:57:46
    make -j#编译时需要开多线程编译,节省时间。j后面的数字应该为CPU核心数的两倍。 比如,这个电脑。8-CORe,8核心,则make -j16 一个CPU核心,就是一个大脑,一个大脑可以同时做两件事。 这个就是英特尔公司超线程...
  • Linux上编译安装和卸载软件(./configure && make && make install )
  • CPU个数、核心数、make编译最大的线程数1、查看物理CPU个数2、查看核心数量3、查看线程数4、查看CPU信息(型号) 查看CPU的常用命令 [wyn11@localhost ~]$ lscpu 架构: x86_64 CPU 运行模式: 32-bit, 64-bit 字节...
  • Make sure you do it as quickly as possible! 2、Reader/writer semphopres 读写信号量 Allow shared access by unlimited readers, or by only 1 writer. Writers get priority. 允许有限数量的读访问,但是只能...
  • Qt Create多核编译配置

    2020-12-08 14:20:58
    Make arguments: 填写 -j4 表示CPU使用4个核进行代码编译。 方法2:该方法可以使用于所有项目编译。 在Qt create的菜单栏点击"工具"--->"选项"--->"构建与运行"--->"构建套件"--->"自动检测”,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,806
精华内容 3,122
热门标签
关键字:

linux make 多核