0

I have a parallel utility class that I would like to be able to use future or openmp, depending on what's available on the system. The future code works fine, but when I pass a function pointer into openmp, I get a linker error, (but if I apply openmp for loop directly to a function there is no error. Here is the code to the parallel loop function from the utility file:

#include "ParallelUtils.h"

#define _OPENMP // just for testing, openmp is installed and verified working
#if defined(_OPENMP)
#include <omp.h>
#elif defined(_WIN32)
#include <Windows.h>
#else
#include <future>
#endif

void ParallelUtils::ParallelFor(size_t From, size_t To, const std::function<void(size_t)> &F)
{
#if defined(_OPENMP)
    #pragma omp parallel for num_threads(To)
    {
        size_t i = omp_get_thread_num();
        F(i);
    }
#elif defined(_WIN32)
    concurrency::parallel_for(From, To, [&](size_t i)
    {
        F(i);
    });
#else
    std::vector<std::future<void>> futures;

    for (size_t i = From; i < To; ++i)
    {
        auto fut = std::async([i, F]()
        {
            F(i);
        });
        futures.push_back(std::move(fut));
    }

    for (size_t i = 0; i < futures.size(); ++i)
        futures[i].wait();

    futures.clear();
#endif
}

Again, if I apply it directly to the function it works fine, ex.

        #pragma omp parallel shared(this, &Input, InOffset, blkLen), num_threads(m_treeParams.ThreadDepth())
        {
            size_t i = omp_get_thread_num();
            ProcessLeaf(Input, InOffset + (i * blkLen), m_hashChain, i * CHAIN_SIZE, blkLen);
        }

So two questions, what am I doing wrong, and, is there anything I need to do to add the shared variables to the openmp version of the function?

JGU
  • 879
  • 12
  • 14
  • What is the error? Are you including ``? – NathanOliver Jun 24 '16 at 13:20
  • Error is LNK2001 unresolved external symbol __imp_omp_get_thread_num, and not including functional, but header has #include – JGU Jun 24 '16 at 13:22
  • This is not an exact duplicate, as there is a second half to the question.. – JGU Jun 24 '16 at 13:34
  • 1
    You are unconditionally defining the `_OPENMP` macro, therefore the OpenMP code will be included no matter whether the OpenMP support was turned on in the project settings or not. If the OpenMP support is not turned on, then the OpenMP runtime library won't be added to the list of libraries and a link error will occur. Besides, `_OPENMP` is supposed to have a numeric value matching the supported OpenMP version and there might be code in `omp.h` that gets selectively enabled based on that number. – Hristo Iliev Jun 24 '16 at 13:40
  • I define _OPENMP because this is a test and _WIN32 is already defined, (so I am effectively bypassing the concurrency function code). The working function is from the same source code, so openmp is enabled and working properly in the library. – JGU Jun 24 '16 at 13:47
  • 2
    If OpenMP is enabled in the project settings, then `_OPENMP` will already be defined by the compiler. Could you create a standalone [mcve] that replicates the problem? It could be in the end due to the notoriously buggy OpenMP implementation in MSVC. – Hristo Iliev Jun 24 '16 at 14:06
  • Actually you were right about that, I changed it to USE_OPENMP, and now it works fine. Is there anything I have to do to add the shared variables though, like how do I share the iterator and state vars like in the other loops? – JGU Jun 24 '16 at 14:11
  • Variables defined in outer scopes (encompassing the parallel region) are shared by default unless you have the `default(none)` clause. – Hristo Iliev Jun 24 '16 at 21:29
  • @ Hristo Iliev -There is no default(none) clause set, but the lambda state variables are not being updated outside of the function, (I've debugged and checked). Is there some clause I need to add to the omp parallel line? – JGU Jun 26 '16 at 16:01

0 Answers0