// File: poseidon1214[P]logistic-regression-ftrl-mpi/src/ftrl.h
// Function: FTRL::ftrl()
void ftrl(){
            int batch_num = data->fea_matrix.size() / batch_size;
            int batch_num_min = 0;
            MPI_Allreduce(&batch_num, &batch_num_min, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD);
            for(int epoch = 0; epoch < epochs; epoch++){
                row = 0;
                int batches = 0;
                if(epoch % 5 == 0  || batches % 1000 == 0){
                    std::cout<<"rank "<<rank<<" epoch "<<epoch<<" batch "<<batches<<std::endl;
                    pred->run(loc_w);
                }
                if( (batches == batch_num_min - 1) ) break;
                while(row < data->fea_matrix.size()){
                    batch_gradient_calculate(row);
                    for(int col = 0; col < data->glo_fea_dim; col++){
                        loc_g[col] /= batch_size;
                    }

                    if(rank != 0){//slave nodes send gradient to master node;
                        MPI_Send(loc_g, data->glo_fea_dim, MPI_FLOAT, 0, 99, MPI_COMM_WORLD);
                    }
                    else if(rank == 0){//rank 0 is master node
                        update();
                    }
                    //sync w of all nodes in cluster
                    if(rank == 0){
                        for(int r = 1; r < num_proc; r++){
                            MPI_Send(loc_w, data->glo_fea_dim, MPI_FLOAT, r, 999, MPI_COMM_WORLD);
                        }
                    }
                    else if(rank != 0){
                        MPI_Recv(loc_w, data->glo_fea_dim, MPI_FLOAT, 0, 999, MPI_COMM_WORLD, &status);
                    }
                    MPI_Barrier(MPI_COMM_WORLD);//will it make the procedure slowly? is it necessary?
                }//end row while
                batches++;
            }//end epoch for
        }

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x28(%rbp)
movq 0x40(%rax), %rdi
addq $0x208, %rdi            # imm = 0x208
callq 0x10760
movq -0x28(%rbp), %rcx
movslq 0xc(%rcx), %rcx
xorl %edx, %edx
divq %rcx
movl %eax, -0xc(%rbp)
movl $0x0, -0x10(%rbp)
leaq -0xc(%rbp), %rdi
leaq -0x10(%rbp), %rsi
movl $0x1, %edx
movq 0x110b9(%rip), %rcx     # 0x1afd8
movq 0x1107a(%rip), %r8      # 0x1afa0
movq 0x1107b(%rip), %r9      # 0x1afa8
callq 0x8750
movl $0x0, -0x14(%rbp)
movq -0x28(%rbp), %rcx
movl -0x14(%rbp), %eax
cmpl 0x8(%rcx), %eax
jge 0xa1ae
movq -0x28(%rbp), %rax
movl $0x0, 0x50(%rax)
movl $0x0, -0x18(%rbp)
movl -0x14(%rbp), %eax
movl $0x5, %ecx
cltd
idivl %ecx
cmpl $0x0, %edx
je 0x9f7b
movl -0x18(%rbp), %eax
movl $0x3e8, %ecx            # imm = 0x3E8
cltd
idivl %ecx
cmpl $0x0, %edx
jne 0x9ff3
movq 0x1104e(%rip), %rdi     # 0x1afd0
leaq 0x90db(%rip), %rsi      # 0x13064
callq 0x85e0
movq %rax, %rdi
movq -0x28(%rbp), %rax
movl 0x84(%rax), %esi
callq 0x8b00
movq %rax, %rdi
leaq 0x9107(%rip), %rsi      # 0x130b1
callq 0x85e0
movq %rax, %rdi
movl -0x14(%rbp), %esi
callq 0x8b00
movq %rax, %rdi
leaq 0x90f5(%rip), %rsi      # 0x130b9
callq 0x85e0
movq %rax, %rdi
movl -0x18(%rbp), %esi
callq 0x8b00
movq %rax, %rdi
movq 0x10fba(%rip), %rsi     # 0x1af98
callq 0x8610
movq -0x28(%rbp), %rax
movq 0x48(%rax), %rdi
movq (%rax), %rsi
callq 0xa1c0
movl -0x18(%rbp), %eax
movl -0x10(%rbp), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jne 0xa005
jmp 0xa1ae
jmp 0xa007
movq -0x28(%rbp), %rax
movslq 0x50(%rax), %rcx
movq %rcx, -0x30(%rbp)
movq 0x40(%rax), %rdi
addq $0x208, %rdi            # imm = 0x208
callq 0x10760
movq %rax, %rcx
movq -0x30(%rbp), %rax
cmpq %rcx, %rax
jae 0xa197
movq -0x28(%rbp), %rdi
movq %rdi, %rsi
addq $0x50, %rsi
callq 0x110a0
movl $0x0, -0x1c(%rbp)
movq -0x28(%rbp), %rcx
movslq -0x1c(%rbp), %rax
movq 0x40(%rcx), %rcx
cmpq 0x2a0(%rcx), %rax
jge 0xa089
movq -0x28(%rbp), %rax
cvtsi2ssl 0xc(%rax), %xmm1
movq 0x58(%rax), %rax
movslq -0x1c(%rbp), %rcx
movss (%rax,%rcx,4), %xmm0
divss %xmm1, %xmm0
movss %xmm0, (%rax,%rcx,4)
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0xa04a
movq -0x28(%rbp), %rax
cmpl $0x0, 0x84(%rax)
je 0xa0c8
movq -0x28(%rbp), %rax
movq 0x58(%rax), %rdi
movq 0x40(%rax), %rax
movq 0x2a0(%rax), %rax
movl %eax, %esi
movq 0x10f06(%rip), %rdx     # 0x1afb8
xorl %ecx, %ecx
movl $0x63, %r8d
movq 0x10ee7(%rip), %r9      # 0x1afa8
callq 0x81e0
jmp 0xa0e0
movq -0x28(%rbp), %rax
cmpl $0x0, 0x84(%rax)
jne 0xa0de
movq -0x28(%rbp), %rdi
callq 0x11310
jmp 0xa0e0
movq -0x28(%rbp), %rax
cmpl $0x0, 0x84(%rax)
jne 0xa140
movl $0x1, -0x20(%rbp)
movq -0x28(%rbp), %rcx
movl -0x20(%rbp), %eax
cmpl 0x80(%rcx), %eax
jge 0xa13e
movq -0x28(%rbp), %rax
movq (%rax), %rdi
movq 0x40(%rax), %rax
movq 0x2a0(%rax), %rax
movl %eax, %esi
movl -0x20(%rbp), %ecx
movq 0x10e97(%rip), %rdx     # 0x1afb8
movl $0x3e7, %r8d            # imm = 0x3E7
movq 0x10e7a(%rip), %r9      # 0x1afa8
callq 0x81e0
movl -0x20(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x20(%rbp)
jmp 0xa0f4
jmp 0xa186
movq -0x28(%rbp), %rax
cmpl $0x0, 0x84(%rax)
je 0xa184
movq -0x28(%rbp), %rax
movq (%rax), %rdi
movq 0x40(%rax), %rcx
movq 0x2a0(%rcx), %rcx
movl %ecx, %esi
addq $0x28, %rax
movq 0x10e4c(%rip), %rdx     # 0x1afb8
xorl %ecx, %ecx
movl $0x3e7, %r8d            # imm = 0x3E7
movq 0x10e2d(%rip), %r9      # 0x1afa8
movq %rax, (%rsp)
callq 0x84e0
jmp 0xa186
movq 0x10e1b(%rip), %rdi     # 0x1afa8
callq 0x83f0
jmp 0xa007
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0x9f39
addq $0x40, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
nop