// File: ArashPartow[P]exprtk-extras/exprtk_vector_benchmark_multithreaded.cpp
// Function: void run_threaded_benchmark<double>(unsigned long const&, unsigned long const&)
void run_threaded_benchmark(const std::size_t& vec_size, const std::size_t& thread_count)
{
   std::vector<std::thread> thread_list;

   exprtk::timer timer;

   timer.start();

   for (std::size_t i = 0; i < thread_count; ++i)
   {
      thread_list.emplace_back(
         std::thread([vec_size]()
                     {
                        for (std::size_t e = 0; e < global_expression_list_size; ++e)
                        {
                           run_expression_benchmark<T>(
                              vec_size,
                              global_expression_list[e].expression,
                              global_expression_list[e].cost);
                        }
                     }));
   }

   for (auto& t : thread_list)
   {
      t.join();
   }

   timer.stop();

   unsigned long long total_flops = 0;

   for (std::size_t i = 0; i < global_expression_list_size; ++i)
   {
      total_flops += global_expression_list[i].cost;
   }

   total_flops = (total_flops * rounds * vec_size * thread_count);

   printf("Total Time:%10.7f FLOP: %llu Perf: %7.4fGFLOPS\n",
          timer.time(),
          total_flops,
          total_flops / (1e9 * timer.time()));
}

// Assembly:
subq $0xc8, %rsp
movq %rdi, 0xc0(%rsp)
movq %rsi, 0xb8(%rsp)
leaq 0xa0(%rsp), %rdi
callq 0x11cd80
leaq 0x78(%rsp), %rdi
callq 0x11cd90
jmp 0x11c890
leaq 0x78(%rsp), %rdi
callq 0x11cdc0
jmp 0x11c89c
movq $0x0, 0x60(%rsp)
movq 0x60(%rsp), %rax
movq 0xb8(%rsp), %rcx
cmpq (%rcx), %rax
jae 0x11c936
movq 0xc0(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x50(%rsp)
leaq 0x58(%rsp), %rdi
leaq 0x50(%rsp), %rsi
callq 0x11ce60
jmp 0x11c8d8
leaq 0xa0(%rsp), %rdi
leaq 0x58(%rsp), %rsi
callq 0x11cde0
jmp 0x11c8ec
leaq 0x58(%rsp), %rdi
callq 0x11cf20
movq 0x60(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x60(%rsp)
jmp 0x11c8a5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x70(%rsp)
movl %eax, 0x6c(%rsp)
jmp 0x11cac6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x70(%rsp)
movl %eax, 0x6c(%rsp)
leaq 0x58(%rsp), %rdi
callq 0x11cf20
jmp 0x11cac6
leaq 0xa0(%rsp), %rax
movq %rax, 0x48(%rsp)
movq 0x48(%rsp), %rdi
callq 0x11cf40
movq %rax, 0x40(%rsp)
movq 0x48(%rsp), %rdi
callq 0x11cf70
movq %rax, 0x38(%rsp)
leaq 0x40(%rsp), %rdi
leaq 0x38(%rsp), %rsi
callq 0x11cfa0
testb $0x1, %al
jne 0x11c976
jmp 0x11c99f
leaq 0x40(%rsp), %rdi
callq 0x11cfe0
movq %rax, 0x30(%rsp)
movq 0x30(%rsp), %rdi
callq 0x113230
jmp 0x11c991
jmp 0x11c993
leaq 0x40(%rsp), %rdi
callq 0x11cff0
jmp 0x11c961
leaq 0x78(%rsp), %rdi
callq 0x11d010
jmp 0x11c9ab
movq $0x0, 0x28(%rsp)
movq $0x0, 0x20(%rsp)
cmpq $0x28, 0x20(%rsp)
jae 0x11c9f2
leaq 0x516554(%rip), %rax    # 0x632f20
imulq $0x28, 0x20(%rsp), %rcx
addq %rcx, %rax
movq (%rax), %rax
addq 0x28(%rsp), %rax
movq %rax, 0x28(%rsp)
movq 0x20(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x20(%rsp)
jmp 0x11c9bd
movq 0x28(%rsp), %rax
movq 0xc0(%rsp), %rcx
movq (%rcx), %rcx
imulq %rcx, %rax
movq 0xb8(%rsp), %rcx
movq (%rcx), %rcx
imulq %rcx, %rax
imulq $0x7d0, %rax, %rax      # imm = 0x7D0
movq %rax, 0x28(%rsp)
leaq 0x78(%rsp), %rdi
callq 0x11d040
movsd %xmm0, 0x18(%rsp)
jmp 0x11ca33
movq 0x28(%rsp), %rax
movq %rax, (%rsp)
movq %rax, %xmm0
movaps 0x3395c8(%rip), %xmm1   # 0x456010
punpckldq %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
movapd 0x3395cc(%rip), %xmm1   # 0x456020
subpd %xmm1, %xmm0
movaps %xmm0, %xmm1
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm1, %xmm0
movsd %xmm0, 0x8(%rsp)
leaq 0x78(%rsp), %rdi
callq 0x11d040
movsd %xmm0, 0x10(%rsp)
jmp 0x11ca7b
movq (%rsp), %rsi
movsd 0x18(%rsp), %xmm0
movsd 0x8(%rsp), %xmm1
movsd 0x10(%rsp), %xmm2
movsd 0x3395a7(%rip), %xmm3   # 0x456040
mulsd %xmm3, %xmm2
divsd %xmm2, %xmm1
leaq 0x33eda8(%rip), %rdi    # 0x45b850
movb $0x2, %al
callq 0x113080
jmp 0x11cab1
leaq 0xa0(%rsp), %rdi
callq 0x11d090
addq $0xc8, %rsp
retq
leaq 0xa0(%rsp), %rdi
callq 0x11d090
movq 0x70(%rsp), %rdi
callq 0x113490
nopl (%rax)