Quantcast
Channel: Intel® Software - OpenCL*
Viewing all articles
Browse latest Browse all 1182

Hang on Linux when initializing OpenCL context from TBB thread

$
0
0

Hi, I'm getting a hang/deadlock when when initializing an Intel OpenCL context from a TBB thread on Linux. On Windows, it's fine. Please try the attached source code.

 

// ocl_test.cpp
//
// Compile with: g++ -std=c++14 -I/path/to/opencl/include -I/path/to/tbb/include -lOpenCL -ltbb -lpthread -L. ocl_test.cpp -o ocl_test
//
// cl.hpp used from: https://www.khronos.org/registry/OpenCL/api/2.1/cl.hpp
//
// Run with:
// $ cd /path/to/parent/dir/libintelocl.so
// $ env LD_LIBRARY_PATH=. LD_PRELOAD=libintelocl.so ./ocl_test
//
// This hangs on Linux under various Intel processors but not Windows
//
#include <iostream>
#include <future>
#include <atomic>
#include <vector>

#define __CL_ENABLE_EXCEPTIONS
#define CL_TARGET_OPENCL_VERSION 120
#include "cl.hpp"

#ifdef _WIN32
#ifdef _DEBUG
    #pragma comment(lib, "OpenCL_d")
    #pragma comment(lib, "tbb_debug")
#else
    #pragma comment(lib, "OpenCL")
    #pragma comment(lib, "tbb")
#endif
#endif

//#define TEST_STDTHREAD
#define TEST_TBB

#ifdef TEST_TBB
#include <tbb/tbb.h>

template <typename F>
class LambdaTask : public tbb::task
{
public:
    LambdaTask(const F& f) : myF(f) {
    }
private:
    tbb::task* execute() override {
        if (myF()) {
            return new(tbb::task::allocate_continuation()) LambdaTask(myF);
        }
        return nullptr;
    }
    F myF;
};

template <typename F>
static void EnqueueLambda(const F& f) {
    tbb::task::enqueue(
            *new(tbb::task::allocate_root()) LambdaTask<F>(f) );
}

template <typename F>
static void SpawnAndWaitLambda(const F& f) {
    tbb::task::spawn_root_and_wait(
            *new(tbb::task::allocate_root()) LambdaTask<F>(f) );
}
#endif

int main() {

    std::vector<cl::Platform> platforms;
    cl::Platform::get(&platforms);

    if (platforms.empty()) {
        std::cout << "No platforms found.\n";
        return 1;
    }

    for (const cl::Platform &platform : platforms) {
        std::cout << "Available platform: "<< platform.getInfo<CL_PLATFORM_NAME>() << "\n";
    }

    cl::Platform platform = platforms[0];
    std::cout << "Using platform: "<< platform.getInfo<CL_PLATFORM_NAME>()
              << "\n";

    std::vector<cl::Device> devices;
    platform.getDevices(CL_DEVICE_TYPE_ALL, &devices);
    if (devices.empty()) {
        std::cout << "No devices found.\n";
        return 1;
    }

    cl::Device device = devices[0];
    std::cout << "Using device: "<< device.getInfo<CL_DEVICE_NAME>() << "\n";

    auto create_context = [&]() {
        std::cout << "Attempting to create context"<< std::endl;
        cl::Context context({device});
        std::cout << "Created context"<< std::endl;
    };

#if defined(TEST_STDTHREAD)

    std::cout << "TEST_STDTHREAD"<< std::endl;
    auto task = std::async(std::launch::async, [&]() { create_context(); });
    task.wait();
    std::cout << "Done"<< std::endl;

#elif defined(TEST_TBB)

    std::cout << "TEST_TBB"<< std::endl;

    std::atomic_bool done(false);

    EnqueueLambda([&]() {
        create_context();
        done = true;
        return false;
    });

#if 1
    // Try waiting inside scheduler loop
    SpawnAndWaitLambda([&]() {
        if (done)
        {
            std::cout << "Done"<< std::endl;
            return false;
        }
        return true;
    });
#else
    // This also fails if we just spin loop
    while (!done)
        ;
    std::cout << "Done"<< std::endl;
#endif

#else
    std::cout << "TEST_SERIAL"<< std::endl;
    create_context();
    std::cout << "Done"<< std::endl;
#endif

    return 0;
}

 

AttachmentSize
Downloadtext/x-c++srcocl_test.cpp3.33 KB

TCE Open Date: 

Friday, December 6, 2019 - 12:51

Viewing all articles
Browse latest Browse all 1182

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>