1

The code:

// g++ -std=c++17 -O0 -g -Wall -Wextra -lOpenCL query.cpp -o query
// valgrind --leak-check=full --track-origins=yes --tool=memcheck ./query N

#include <CL/cl.h>
#include <CL/cl.hpp>
#include <vector>
#include <string>
#include <iostream>
#include <memory>

using namespace std;

#define CL_CHECK_ERROR(error)                                    \
  if ((error) != CL_SUCCESS){ cout << "ERROR in " << __FILE__ << ":" << __LINE__ << "\n"; }

int main(int, char * argv[])
{
  int type = stoi(argv[1]);

  string info_buffer;
  int info_buffer_size = 1024;
  info_buffer.reserve(info_buffer_size);

  if (type == 0){

    vector<cl_platform_id> platforms;
    cl_uint num_platforms;

    CL_CHECK_ERROR(clGetPlatformIDs(0, NULL, &num_platforms));
    cout << "num_platforms: " << num_platforms << "\n";
    platforms.reserve(num_platforms);
    platforms.resize(num_platforms);
    CL_CHECK_ERROR(clGetPlatformIDs(num_platforms, platforms.data(), NULL));
    cout << "- " << platforms.data()[0] << "\n";
    // cout << "- " << platforms.data()[1] << "\n";
    // cout << platforms.size() << "\n";
    for (auto& platform : platforms){
      cout << platform << "\n";
      size_t size;
      CL_CHECK_ERROR(clGetPlatformInfo(platform, CL_PLATFORM_NAME, 0, NULL, &size));
      info_buffer.resize(size); // works also with size - 1
      CL_CHECK_ERROR(clGetPlatformInfo(platform, CL_PLATFORM_NAME, size, info_buffer.data(), NULL));
      cout << "platform: '" << info_buffer << "'\n";
    }

  }else if (type == 1){

    cl_uint num_platforms;

    CL_CHECK_ERROR(clGetPlatformIDs(0, NULL, &num_platforms));
    cout << "num_platforms: " << num_platforms << "\n";
    unique_ptr<cl_platform_id[]> platforms(new cl_platform_id[num_platforms]);

    CL_CHECK_ERROR(clGetPlatformIDs(num_platforms, platforms.get(), NULL));
    cout << "- " << platforms[0] << "\n";
    // cout << "- " << platforms[1] << "\n";
    for (uint i=0; i<num_platforms; i++){
      cl_platform_id platform = platforms[i];
      cout << platforms[i] << "\n";
      size_t size;
      CL_CHECK_ERROR(clGetPlatformInfo(platform, CL_PLATFORM_NAME, 0, NULL, &size));
      info_buffer.resize(size); // works also with size - 1
      CL_CHECK_ERROR(clGetPlatformInfo(platform, CL_PLATFORM_NAME, size, info_buffer.data(), NULL));
      cout << "platform: '" << info_buffer << "'\n";
    }

  } else {
    vector<cl::Platform> platforms;
    cl::Platform::get(&platforms);
    cout << "num_platforms: " << platforms.size() << "\n";
    cout << "- " << platforms.at(0)() << "\n";
    // cout << "- " << platforms[1] << "\n";
    for (auto& platform : platforms) {
      CL_CHECK_ERROR(platform.getInfo(CL_PLATFORM_NAME, &info_buffer));
      cout << "platform: " << info_buffer << "\n";
    }
  }

  return 0;
}

The compilation:

g++ -std=c++17 -O0 -g -Wall -Wextra -lOpenCL query.cpp -o query

Valgrind:

valgrind --leak-check=full --track-origins=yes --tool=memcheck ./query 0 2>query_t0.memcheck

valgrind --leak-check=full --track-origins=yes --tool=memcheck ./query 1 2>query_t1.memcheck

valgrind --leak-check=full --track-origins=yes --tool=memcheck ./query 2 2>query_t2.memcheck

In t0 and t1 cases (.h):

==8877== LEAK SUMMARY:
==8877==    definitely lost: 2,804 bytes in 19 blocks
==8877==    indirectly lost: 1,444 bytes in 9 blocks
==8877==      possibly lost: 152 bytes in 1 blocks
==8877==    still reachable: 3,056,953 bytes in 1,706 blocks
==8877==                       of which reachable via heuristic:
==8877==                         newarray           : 7,192 bytes in 7 blocks
==8877==         suppressed: 0 bytes in 0 blocks
==8877== Reachable blocks (those to which a pointer was found) are not shown.
==8877== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==8877==
==8877== For counts of detected and suppressed errors, rerun with: -v
==8877== ERROR SUMMARY: 231 errors from 76 contexts (suppressed: 1 from 1)

In t2 (.hpp):

==32316== LEAK SUMMARY:
==32316==    definitely lost: 2,956 bytes in 20 blocks
==32316==    indirectly lost: 1,444 bytes in 9 blocks
==32316==      possibly lost: 0 bytes in 0 blocks
==32316==    still reachable: 3,056,953 bytes in 1,706 blocks
==32316==                       of which reachable via heuristic:
==32316==                         newarray           : 7,192 bytes in 7 blocks
==32316==         suppressed: 0 bytes in 0 blocks
==32316== Reachable blocks (those to which a pointer was found) are not shown.
==32316== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==32316==
==32316== For counts of detected and suppressed errors, rerun with: -v
==32316== ERROR SUMMARY: 230 errors from 75 contexts (suppressed: 1 from 1)

Some errors (from the t2):

==32316== 168 (144 direct, 24 indirect) bytes in 1 blocks are definitely lost in loss record 1,201 of 1,366
==32316==    at 0x4C2CEBF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==32316==    by 0xB4DDF64: Priv_Main_Control_Refresh() (in /usr/lib/libatiadlxx.so)
==32316==    by 0xB4E669F: ADL_Main_Control_Refresh_X() (in /usr/lib/libatiadlxx.so)
==32316==    by 0xB4F3073: ADL2_Main_Control_Refresh (in /usr/lib/libatiadlxx.so)
==32316==    by 0xB4F58E1: ADL2_Main_Control_Create (in /usr/lib/libatiadlxx.so)
==32316==    by 0x7A50470: ??? (in /usr/lib/libamdocl64.so)
==32316==    by 0x7D6F340: ??? (in /usr/lib/libamdocl64.so)
==32316==    by 0x7D3F8C6: ??? (in /usr/lib/libamdocl64.so)
==32316==    by 0x7D3F91B: ??? (in /usr/lib/libamdocl64.so)
==32316==    by 0x7D44C73: ??? (in /usr/lib/libamdocl64.so)
==32316==    by 0x7D2E7C6: ??? (in /usr/lib/libamdocl64.so)
==32316==    by 0x7A27F26: ??? (in /usr/lib/libamdocl64.so)
==32316==
==32316== 278 (240 direct, 38 indirect) bytes in 1 blocks are definitely lost in loss record 1,225 of 1,366
==32316==    at 0x4C2D51F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==32316==    by 0x63C2DD7: ??? (in /opt/intel/opencl-runtime/lib64/libintelocl.so)
==32316==    by 0x6339563: ??? (in /opt/intel/opencl-runtime/lib64/libintelocl.so)
==32316==    by 0x6339F61: ??? (in /opt/intel/opencl-runtime/lib64/libintelocl.so)
==32316==    by 0x634FD84: clGetPlatformIDs (in /opt/intel/opencl-runtime/lib64/libintelocl.so)
==32316==    by 0x4E3EBD1: ??? (in /usr/lib/libOpenCL.so.1.0.0)
==32316==    by 0x4E3FE83: clGetPlatformIDs (in /usr/lib/libOpenCL.so.1.0.0)
==32316==    by 0x10B77C: cl::Platform::get(std::vector<cl::Platform, std::allocator<cl::Platform> >*) (cl.hpp:2338)
==32316==    by 0x10B143: main (query.cpp:69)
==32316==
==32316== 286 (248 direct, 38 indirect) bytes in 1 blocks are definitely lost in loss record 1,227 of 1,366
==32316==    at 0x4C2D51F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==32316==    by 0x63C2F09: ??? (in /opt/intel/opencl-runtime/lib64/libintelocl.so)
==32316==    by 0x6339563: ??? (in /opt/intel/opencl-runtime/lib64/libintelocl.so)
==32316==    by 0x6339F61: ??? (in /opt/intel/opencl-runtime/lib64/libintelocl.so)
==32316==    by 0x634FD84: clGetPlatformIDs (in /opt/intel/opencl-runtime/lib64/libintelocl.so)
==32316==    by 0x4E3EBD1: ??? (in /usr/lib/libOpenCL.so.1.0.0)
==32316==    by 0x4E3FE83: clGetPlatformIDs (in /usr/lib/libOpenCL.so.1.0.0)
==32316==    by 0x10B77C: cl::Platform::get(std::vector<cl::Platform, std::allocator<cl::Platform> >*) (cl.hpp:2338)
==32316==    by 0x10B143: main (query.cpp:69)
==32316==
==32316== 512 bytes in 1 blocks are definitely lost in loss record 1,252 of 1,366
==32316==    at 0x4C2D51F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==32316==    by 0x63EEAA5: ??? (in /opt/intel/opencl-runtime/lib64/libintelocl.so)
==32316==    by 0x63F4526: ??? (in /opt/intel/opencl-runtime/lib64/libintelocl.so)
==32316==    by 0x63F4B73: ??? (in /opt/intel/opencl-runtime/lib64/libintelocl.so)
==32316==    by 0x6339486: ??? (in /opt/intel/opencl-runtime/lib64/libintelocl.so)
==32316==    by 0x6339F61: ??? (in /opt/intel/opencl-runtime/lib64/libintelocl.so)
==32316==    by 0x634FD84: clGetPlatformIDs (in /opt/intel/opencl-runtime/lib64/libintelocl.so)
==32316==    by 0x4E3EBD1: ??? (in /usr/lib/libOpenCL.so.1.0.0)
==32316==    by 0x4E3FE83: clGetPlatformIDs (in /usr/lib/libOpenCL.so.1.0.0)
==32316==    by 0x10B77C: cl::Platform::get(std::vector<cl::Platform, std::allocator<cl::Platform> >*) (cl.hpp:2338)
==32316==    by 0x10B143: main (query.cpp:69)
==32316==
==32316== 1,520 bytes in 10 blocks are definitely lost in loss record 1,290 of 1,366
==32316==    at 0x4C2CEBF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==32316==    by 0xD45BEBD: amdcl::scCompileImpl::Text2Stream(amdcl::_il_string_rec const&, amdcl::_il_binary_rec&) (in /usr/lib/libamdocl12cl64.so)
==32316==    by 0xD463218: amdcl::AMDIL::toBinary(char const*, unsigned long*) (in /usr/lib/libamdocl12cl64.so)
==32316==    by 0xD4646BD: amdcl::AMDIL::compile(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, amdcl::scCompileBase*) (in /usr/lib/libamdocl12cl64.so)
==32316==    by 0xD46306F: amdcl::AMDIL::compile(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) (in /usr/lib/libamdocl12cl64.so)
==32316==    by 0xCF80AB3: AMDILFEToISA(_acl_loader_data_0_8**, char const*, unsigned long) (in /usr/lib/libamdocl12cl64.so)
==32316==    by 0xCF828B4: if_aclCompile(_acl_compiler_rec_0_8_1*, _acl_bif_rec_0_8_1*, char const*, _acl_type_enum_0_8, _acl_type_enum_0_8, void (*)(char const*, unsigned long)) (in /usr/lib/libamdocl12cl64.so)
==32316==    by 0x82C35D8: aclCompile (in /usr/lib/libamdocl64.so)
==32316==    by 0x79930E7: ??? (in /usr/lib/libamdocl64.so)
==32316==    by 0x799375F: ??? (in /usr/lib/libamdocl64.so)
==32316==    by 0x79A2111: ??? (in /usr/lib/libamdocl64.so)
==32316==    by 0x79A4929: ??? (in /usr/lib/libamdocl64.so)

As you can see, I have tried three different ways to query the platforms (t0, t1 using the C API, t2 using the C++ API). How can I remove the memory leaks in my code? Am I doing something wrong?

From those 231 errors from 76 contexts, my file appears in just 4 (C) or 3 (C++) messages (grep 'cpp' query_t1.memcheck vs grep 'lost' query_t1.memcheck). So, how can I remove those memory leaks if are not leaked from my code? Can I do something there?

Example:

==32316==    by 0x10B143: main (query.cpp:69)
==32316==    by 0x10B143: main (query.cpp:69)
==32316==    by 0x10B143: main (query.cpp:69)

==32316== 8 bytes in 1 blocks are definitely lost in loss record 53 of 1,366
==32316== 8 bytes in 1 blocks are definitely lost in loss record 54 of 1,366
==32316== 8 bytes in 1 blocks are definitely lost in loss record 55 of 1,366
==32316== 8 bytes in 1 blocks are definitely lost in loss record 56 of 1,366
==32316== 20 bytes in 1 blocks are definitely lost in loss record 94 of 1,366
==32316== 168 (144 direct, 24 indirect) bytes in 1 blocks are definitely lost in loss record 1,201 of 1,366
==32316== 278 (240 direct, 38 indirect) bytes in 1 blocks are definitely lost in loss record 1,225 of 1,366
==32316== 286 (248 direct, 38 indirect) bytes in 1 blocks are definitely lost in loss record 1,227 of 1,366
==32316== 512 bytes in 1 blocks are definitely lost in loss record 1,252 of 1,366
==32316== 1,520 bytes in 10 blocks are definitely lost in loss record 1,290 of 1,366
==32316== 1,584 (240 direct, 1,344 indirect) bytes in 1 blocks are definitely lost in loss record 1,291 of 1,366
==32316==    definitely lost: 2,956 bytes in 20 blocks
==32316==    indirectly lost: 1,444 bytes in 9 blocks
==32316==      possibly lost: 0 bytes in 0 blocks
user3819881
  • 377
  • 3
  • 13

1 Answers1

2

Ran your program with pocl git master in valgrind, results:

==21413== Memcheck, a memory error detector
==21413== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==21413== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==21413== Command: ./query 1
==21413== 
num_platforms: 1
- 0x840df40
0x840df40
platform: 'Portable Computing Language'
==21413== 
==21413== HEAP SUMMARY:
==21413==     in use at exit: 74,145 bytes in 858 blocks
==21413==   total heap usage: 1,058 allocs, 200 frees, 421,333 bytes allocated
==21413== 
==21413== LEAK SUMMARY:
==21413==    definitely lost: 0 bytes in 0 blocks
==21413==    indirectly lost: 0 bytes in 0 blocks
==21413==      possibly lost: 0 bytes in 0 blocks
==21413==    still reachable: 74,145 bytes in 858 blocks
==21413==         suppressed: 0 bytes in 0 blocks
==21413== Reachable blocks (those to which a pointer was found) are not shown.
==21413== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==21413== 
==21413== For counts of detected and suppressed errors, rerun with: -v
==21413== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

So...

How can I remove the memory leaks in my code? Am I doing something wrong?

You're not doing anything wrong. The AMD/Intel implementations are not exactly memleak-free :)

mogu
  • 1,091
  • 6
  • 8
  • Thank you. I will mark your answer as solved after you answer this comment. One question (try to be detailed). The "Still reachable" gives you 74KB, how would you remove that? is it problematic? – user3819881 Dec 20 '17 at 12:10
  • @user3819881 Again not a problem in your code. Those 74KB are leaked on each program run by pocl (sadly this is likely non-fixable in pocl, because it happens inside libLLVM). Also not terribly problematic since this happens only once, at program startup. AFAICT your code has zero memleaks. But if you want to write host-side code in C++, you may find it worthwhile to learn the C++ interface (cl.hpp / cl2.hpp) which would make memory & error handling a lot easier (and your code shorter & nicer). – mogu Dec 20 '17 at 15:54
  • Ok, thanks. I used both cl.hpp and cl.h. I was returning to use cl.h in case they wrote the cl.hpp interface even worst (with more memory leaks). I set accepted your answer. – user3819881 Dec 21 '17 at 16:51