[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/codeplaysoftware/computecpp-sdk/master/samples/smart-pointer.cpp [Back]  [Original]

/***************************************************************************
 *
 *  Copyright (C) 2016 Codeplay Software Limited
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  For your convenience, a copy of the License has been included in this
 *  repository.
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *  Codeplay's ComputeCpp SDK
 *
 *  smart-pointer.cpp
 *
 *  Description:
 *    Sample code that shows how SYCL can use custom allocators.
 *
 **************************************************************************/

#include 

// Custom stack allocator
#include "stack_allocator.hpp"

using namespace cl::sycl;

class kernel0;
class kernel1;
class kernel2;

int main() {
  const unsigned int nElems = 12;
  std::shared_ptr p(new int[nElems]);
  bool correct = true;
  for (unsigned int i = 0; i < nElems; i++) {
    p.get()[i] = 0;
  }

  queue myQueue;

  {
    /* Buffers can take a shared_ptr as a parameter, and they
     * will share ownership of the pointer.
     * Data will be copied back only if the user still keeps
     * a reference of the data. */
    {
      buffer buf(p, range(nElems));

      myQueue.submit([&](handler& cgh) {
        auto myRange = nd_range(range(6, 2), range(2, 1));

        auto ptr = buf.get_access(cgh);
        cgh.parallel_for(myRange, [=](nd_item itemID) {
          ptr[itemID.get_global_linear_id()] =
              itemID.get_global_linear_id();
        });
      });
      {
        /* The runtime will make data available via hA. It might use mapped
         * memory, temporary objects or internal allocations. It is up to
         * the implementation. The original pointer is not updated. */
        auto hA = buf.get_access();

        int sum = 0;
        for (unsigned int i = 0; i < nElems; i++) {
          sum += hA[i];
        }

        if (sum != 66) {
          correct = false;
        }
      }
    }

    /* Data now available in the original pointer, because the buffer
     * has been destroyed. */
    int sum = 0;
    for (unsigned int i = 0; i < nElems; i++) {
      sum += p.get()[i];
    }

    if (sum != 66) {
      correct = false;
    }
  }

  {
    /* Custom allocators can be used - here we use a stack_allocator from
     * https://github.com/charles-salvia/charles/blob/master/stack_allocator.hpp
     */
    {
      buffer buf{range{nElems}};
      /* buffer::set_final_data() tells the runtime that the data should be
       * copied to p when the buffer is destroyed. */
      buf.set_final_data(p);

      myQueue.submit([&](handler& cgh) {
        auto myRange = nd_range(range(6, 2), range(2, 1));

        auto ptr = buf.get_access(cgh);
        cgh.parallel_for(myRange, [=](nd_item itemID) {
          ptr[itemID.get_global_linear_id()] = itemID.get_global_linear_id();
        });
      });
    }

    /* The buffers have now been destroyed, and the data copied in to p. */
    int sum = 0;
    for (unsigned int i = 0; i < nElems; i++) {
      sum += p.get()[i];
    }

    if (sum != 66) {
      correct = false;
    }
  }

  {
    {
      /* The property "use_host_ptr" tells the runtime that the user
       * pointer passed to the constructor should be used to store all
       * data, rather than new internal allocations. When using this,
       * all host accessors update the user-given host memory. This can
       * improve performance, though you should always profile to see
       * if it actually makes a difference. */
      buffer buf(p, range(nElems),
                         {property::buffer::use_host_ptr()});

      myQueue.submit([&](handler& cgh) {
        auto myRange = nd_range(range(6, 2), range(2, 1));

        auto ptr = buf.get_access(cgh);
        cgh.parallel_for(myRange, [=](nd_item itemID) {
          ptr[itemID.get_global_linear_id()] =
              itemID.get_global_linear_id();
        });
      });

      {
        /* Host accessors will actually block on creation, so in this case we
         * know kernel2 has finished by the time hA is available. */
        auto hA = buf.get_access();

        int sum = 0;
        for (unsigned int i = 0; i < nElems; i++) {
          sum += p.get()[i];
        }

        if (sum != 66) {
          correct = false;
        }
      }
    }
    /* Normally data is copied to the host when buffers are destroyed, which
     * would happen here, but since `use_host_ptr` and a host accessor were
     * used in concert no data copy happens (i.e., has *already* happened). */
  }

  return correct ? 0 : 1;
}

Web Proxy Viewer  |  New URL  |  Original Page