{"id":110,"date":"2017-10-23T18:53:38","date_gmt":"2017-10-23T09:53:38","guid":{"rendered":"http:\/\/www.sciement.com\/tech-blog\/?p=110"},"modified":"2017-12-21T17:40:09","modified_gmt":"2017-12-21T08:40:09","slug":"various_binarizations","status":"publish","type":"post","link":"https:\/\/www.sciement.com\/tech-blog\/c\/various_binarizations\/","title":{"rendered":"[C++][CUDA][PPL][AMP]\u5358\u7d14\u306a\u4e8c\u5024\u5316\u51e6\u7406\u30924\u901a\u308a\u306e\u4e26\u5217\u5316\u624b\u6cd5\u3067\u6bd4\u8f03\u3057\u3066\u307f\u308b"},"content":{"rendered":"<p>\u753b\u50cf\u51e6\u7406\u306e\u5206\u91ce\u306b\u304a\u3044\u3066\u3001\u5404\u30d4\u30af\u30bb\u30eb\uff08\u7a7a\u9593\u306e\u5834\u5408\u306f\u5404\u30dc\u30af\u30bb\u30eb\uff09\u306e\u5024\u30920\u304b1\u304b\u306e\u3069\u3061\u3089\u304b\u306e\u5024\u306b\u5206\u3051\u308b\u4e8c\u5024\u5316\u51e6\u7406\u304c\u983b\u7e41\u306b\u884c\u308f\u308c\u307e\u3059\u3002<br \/>\n\u4f55\u3092\u4ee5\u30660\u307e\u305f\u306f1\u3068\u3059\u308b\u304b\u304c\u30dd\u30a4\u30f3\u30c8\u306a\u308f\u3051\u3067\u3059\u304c\u3001\u3053\u3053\u3067\u306f\u8d85\u7c21\u5358\u306b\u3001\u95be\u5024\uff08threshold\uff09\u672a\u6e80\u3060\u3063\u305f\u30891\u3001\u4ee5\u4e0a\u3060\u3063\u305f\u30890\u306b\u306a\u308b\u3053\u3068\u3092\u8003\u3048\u3066\u307f\u307e\u3059\u3002<\/p>\n<p>\u4f8b\u3048\u3070\u5168\u90e8\u30678\u30d4\u30af\u30bb\u30eb\u306e\u753b\u50cf\u3067\u3001\u5404\u30d4\u30af\u30bb\u30eb\u306e\u5024\u304cint\u578b\u3067\u4e0e\u3048\u3089\u308c\u3066\u3044\u308b\u3068\u304d\u306b\u95be\u502440\u3067\u3042\u308c\u3070\u4ee5\u4e0b\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-111\" src=\"http:\/\/www.sciement.com\/tech-blog\/wp-content\/uploads\/2017\/10\/binarization.jpg\" alt=\"\" width=\"1800\" height=\"500\" srcset=\"https:\/\/www.sciement.com\/tech-blog\/wp-content\/uploads\/2017\/10\/binarization.jpg 1800w, https:\/\/www.sciement.com\/tech-blog\/wp-content\/uploads\/2017\/10\/binarization-300x83.jpg 300w, https:\/\/www.sciement.com\/tech-blog\/wp-content\/uploads\/2017\/10\/binarization-768x213.jpg 768w, https:\/\/www.sciement.com\/tech-blog\/wp-content\/uploads\/2017\/10\/binarization-1024x284.jpg 1024w\" sizes=\"auto, (max-width: 1800px) 100vw, 1800px\" \/><\/p>\n<p>\u6761\u4ef6\u5f0f\u304c1\u56de\u3057\u304b\u51fa\u3066\u3053\u306a\u3044\u3088\u3046\u306a\u51e6\u7406\u3067\u3082\u3001\u30d4\u30af\u30bb\u30eb\uff08\u30dc\u30af\u30bb\u30eb\uff09\u306e\u7dcf\u6570\u304c\u5927\u304d\u304f\u306a\u308c\u3070\u4e26\u5217\u5316\u306e\u610f\u5473\u304c\u3042\u308b\u306e\u304b\u3069\u3046\u304b\u3092\u691c\u8a3c\u3059\u308b\u305f\u3081\u306b\u3001<br \/>\n\u7e26256, \u6a2a256, \u9ad8\u3055256\uff1a\u5408\u8a0816,777,216\u30dc\u30af\u30bb\u30eb\u306e\u30dc\u30ea\u30e5\u30fc\u30e0\u753b\u50cf\u3092\u4eee\u5b9a\u3057\u3066\u3001<\/p>\n<p>1. CPU\u30b7\u30f3\u30b0\u30eb\u30b9\u30ec\u30c3\u30c9<br \/>\n2. <a href=\"https:\/\/msdn.microsoft.com\/ja-jp\/library\/dd492418.aspx\" target=\"_blank\" rel=\"noopener\"><strong>\u4e26\u5217\u30d1\u30bf\u30fc\u30f3 \u30e9\u30a4\u30d6\u30e9\u30ea (PPL)<\/strong><\/a>\u306b\u3088\u308bfor\u6587\u306e\u30de\u30eb\u30c1\u30b9\u30ec\u30c3\u30c9CPU\u51e6\u7406<br \/>\n3. <a href=\"https:\/\/msdn.microsoft.com\/ja-jp\/library\/hh265137.aspx\" target=\"_blank\" rel=\"noopener\"><strong>C++ AMP (C++ Accelerated Massive Parallelism)<\/strong><\/a>\u306b\u3088\u308bGPGPU\u4e26\u5217\u51e6\u7406<br \/>\n-3-1. <a href=\"https:\/\/msdn.microsoft.com\/ja-jp\/library\/hh305260.aspx\" target=\"_blank\" rel=\"noopener\"><strong>concurrency::array_view<\/strong><\/a>\u306b\u3088\u308b\u3082\u306e<br \/>\n-3-2. <a href=\"https:\/\/msdn.microsoft.com\/ja-jp\/library\/hh305242.aspx\" target=\"_blank\" rel=\"noopener\"><strong>concurrency::array<\/strong><\/a>\u306b\u3088\u308b\u3082\u306e<br \/>\n4. <a href=\"https:\/\/developer.nvidia.com\/cuda-toolkit\" target=\"_blank\" rel=\"noopener\"><strong>CUDA<\/strong><\/a>\u306b\u3088\u308bGPGPU\u4e26\u5217\u51e6\u7406<\/p>\n<p>\u306e\u5408\u8a085\u901a\u308a\u3067\u6bd4\u8f03\u3057\u3066\u307f\u307e\u3057\u305f\u3002<\/p>\n<p>\u4ee5\u4e0b\u3001\u30b3\u30fc\u30c9\u4e00\u5f0f\u3067\u3059\u3002\u30b3\u30fc\u30c9\u306e\u4e0b\u306b\u5b9f\u884c\u7d50\u679c\u3092\u63b2\u8f09\u3057\u307e\u3059\u3002<br \/>\n\u3082\u3061\u308d\u3093PC\u306e\u74b0\u5883\u306b\u3088\u3063\u3066\u6570\u5b57\u306f\u5909\u308f\u308b\u304b\u3068\u601d\u3044\u307e\u3059\u306e\u3067\u3001\u3042\u304f\u307e\u3067\u3082\u53c2\u8003\u5024\u3067\u306f\u3042\u308a\u307e\u3059\u3002<br \/>\n\u30b3\u30fc\u30c9\u306f\u3069\u3046\u3067\u3082\u826f\u3044\u304b\u3089\u7d50\u679c\u3060\u3051\u898b\u305f\u3044\u3068\u3044\u3046\u65b9\u306f\u3001\u3059\u3063\u98db\u3070\u3057\u3066\u4e00\u756a\u4e0b\u306e\u307b\u3046\u3092\u898b\u3066\u304f\u3060\u3055\u3044\u3002<\/p>\n<p>\u4e71\u6570\u306e\u751f\u6210\u65b9\u6cd5\u306f<a href=\"https:\/\/cpplover.blogspot.jp\/2009\/11\/c0xrandom.html\" target=\"_blank\" rel=\"noopener\"><strong>\u672c\u306e\u866b: C++0x\u306e\u65b0\u3057\u3044\u4e71\u6570\u30e9\u30a4\u30d6\u30e9\u30ea\u3001random<\/strong><\/a><br \/>\nC++ AMP\u306e\u30a2\u30af\u30bb\u30e9\u30ec\u30fc\u30bf\u306e\u53d6\u5f97\u30fb\u6c7a\u5b9a\u65b9\u6cd5\u306f<a href=\"https:\/\/qiita.com\/Riyaaaa_a\/items\/40054b893e70b54f5a26\" target=\"_blank\" rel=\"noopener\"><strong>C++ AMP\u306b\u3088\u308bGPGPU\u5165\u9580 &#8211; Qiita<\/strong><\/a><\/p>\n<p>\u3092\u53c2\u8003\u306b\u3055\u305b\u3066\u9802\u304d\u307e\u3057\u305f\u3002<br \/>\n.cu\u30d5\u30a1\u30a4\u30eb\u5185\u3067C++ AMP\u3092\u30a4\u30f3\u30af\u30eb\u30fc\u30c9\u3057\u3088\u3046\u3059\u308b\u3068\u30b3\u30f3\u30d1\u30a4\u30eb\u6642\u306b\u30a8\u30e9\u30fc\u304c\u51fa\u305f\u305f\u3081\u3001.cu\u30d5\u30a1\u30a4\u30eb\u3068\u5bfe\u5fdc\u3059\u308b.h\u30d5\u30a1\u30a4\u30eb\u3001\u305d\u3057\u3066main\u95a2\u6570\u3092\u542b\u3093\u3060.cpp\u30d5\u30a1\u30a4\u30eb\u306e3\u3064\u3092\u4f5c\u308a\u307e\u3057\u305f\u3002<br \/>\n\u3084\u305f\u3089\u3068\u9577\u3044\u3067\u3059\u304c\u3001\u672c\u8cea\u306f\u3069\u308c\u3082\u30cf\u30a4\u30e9\u30a4\u30c8\u3067\u8868\u793a\u3057\u305f1\u884c\u3060\u3051\u3067\u3001\u305d\u306e\u4ed6\u306f\u4e26\u5217\u5316\u306e\u305f\u3081\u306e\u4e0b\u6e96\u5099\u3067\u3042\u3063\u305f\u308a\u3001\u3069\u306e\u624b\u6cd5\u3067\u3082\u540c\u3058\u7d50\u679c\u306b\u306a\u3063\u3066\u3044\u308b\u304b\u306e\u30c1\u30a7\u30c3\u30af\u3060\u3063\u305f\u308a\u3067\u3059\u3002<\/p>\n<pre class=\"lang:c++ mark:42,62,117,164 decode:true \" title=\"test.cpp\">\/\/ Copyright SCIEMENT, Inc.\r\n\/\/ by Hirofumi Seo, M.D., CEO &amp; President\r\n\r\n#include &lt;amp.h&gt;\r\n#include &lt;ppl.h&gt;\r\n#include &lt;chrono&gt;\r\n#include &lt;random&gt;\r\n#include &lt;algorithm&gt;\r\n#include \"CUDA_test.h\"\r\n\r\nint main() {\r\n  \/\/ Make random 2^24 int.\r\n  std::vector&lt;int&gt; voxels;\r\n  const int width = 256;\r\n  const int height = 256;\r\n  const int slice = 256;\r\n  voxels.resize(width * height * slice);\r\n  std::random_device rnd;\r\n  std::vector&lt;std::uint_least32_t&gt; v(10);\r\n  std::generate(v.begin(), v.end(), std::ref(rnd));\r\n  std::mt19937 engine(std::seed_seq(v.begin(), v.end()));\r\n\r\n  std::uniform_int_distribution&lt;int&gt; distribution(-2000, 2000);\r\n  for (auto &amp; value : voxels) {\r\n    value = distribution(engine);\r\n  }\r\n\r\n  const int threshold = 700;\r\n\r\n  std::chrono::time_point&lt;std::chrono::system_clock&gt; start;\r\n  std::chrono::time_point&lt;std::chrono::system_clock&gt; end;\r\n\r\n  std::cout &lt;&lt; \"--------------------------------\" &lt;&lt; std::endl;\r\n\r\n  \/\/ Single CPU\r\n  std::vector&lt;int&gt; bit_vertices_single(voxels.size());\r\n\r\n  start = std::chrono::system_clock::now();\r\n\r\n  int i = 0;\r\n  for (auto&amp; value : voxels) {\r\n    bit_vertices_single[i] = (int)(voxels[i] &lt; threshold);\r\n    ++i;\r\n  }\r\n\r\n  end = std::chrono::system_clock::now();\r\n  auto execution_time = end - start;\r\n  std::cout &lt;&lt; \"Single CPU: \" &lt;&lt; std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(execution_time).count() &lt;&lt; \" msec.\" &lt;&lt; std::endl;\r\n  \/\/ end Single CPU\r\n\r\n  std::cout &lt;&lt; \"--------------------------------\" &lt;&lt; std::endl;\r\n\r\n  \/\/ PPL\r\n  std::vector&lt;int&gt; bit_vertices_ppl(voxels.size());\r\n\r\n  start = std::chrono::system_clock::now();\r\n\r\n  concurrency::parallel_for(int(0), int(slice), [&amp;](int current_slice) {\r\n    for (int current_height = 0; current_height &lt; height; ++current_height) {\r\n      for (int current_width = 0; current_width &lt; width; ++current_width) {\r\n        const int voxel_id = current_width + (current_height + current_slice * height) * width;\r\n        bit_vertices_ppl[voxel_id] = (int)(voxels[voxel_id] &lt; threshold);\r\n      }\r\n    }\r\n  });\r\n  \r\n  end = std::chrono::system_clock::now();\r\n  execution_time = end - start;\r\n  std::cout &lt;&lt; \"PPL: \" &lt;&lt; std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(execution_time).count() &lt;&lt; \" msec.\" &lt;&lt; std::endl;\r\n  \/\/ end PPL\r\n\r\n  \/\/ check Single CPU and PPL\r\n  bool check_ppl = true;\r\n  i = 0;\r\n  for (const auto&amp; value : bit_vertices_ppl) {\r\n    if (value != bit_vertices_single[i]) {\r\n      check_ppl = false;\r\n      break;\r\n    }\r\n    ++i;\r\n  }\r\n  std::cout &lt;&lt; (check_ppl ? \"OK\" : \"ERROR!!\") &lt;&lt; std::endl;\r\n\r\n  std::cout &lt;&lt; \"--------------------------------\" &lt;&lt; std::endl;\r\n\r\n  \/\/ C++ AMP array_view\r\n  std::cout &lt;&lt; \"C++ AMP: \";\r\n\r\n  start = std::chrono::system_clock::now();\r\n  \r\n  std::vector&lt;concurrency::accelerator&gt; gpus = concurrency::accelerator::get_all();\r\n  \/\/ Remove all emulated accelerators.\r\n  gpus.erase(std::remove_if(gpus.begin(), gpus.end(), [](concurrency::accelerator&amp; gpu) { return gpu.get_is_emulated(); }), gpus.end());\r\n  concurrency::accelerator max_memory_gpu = *std::max_element(gpus.begin(), gpus.end(), [](const concurrency::accelerator&amp; rhs, const concurrency::accelerator&amp; lhs) {return rhs.get_dedicated_memory() &lt; lhs.get_dedicated_memory(); });\r\n\r\n  end = std::chrono::system_clock::now();\r\n  execution_time = end - start;\r\n  std::cout &lt;&lt; \"Initialize: \" &lt;&lt; std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(execution_time).count() &lt;&lt; \" msec.\" &lt;&lt; std::endl;\r\n  std::cout &lt;&lt; \"array_view: \" &lt;&lt; std::endl;\r\n  \r\n  std::vector&lt;int&gt; bit_vertices_amp(voxels.size());\r\n\r\n  start = std::chrono::system_clock::now();\r\n\r\n  concurrency::array_view&lt;int, 1&gt; voxels_view(voxels.size(), voxels);\r\n\r\n  concurrency::array_view&lt;int, 1&gt; bit_vertices_amp_view(voxels.size(), bit_vertices_amp);\r\n  bit_vertices_amp_view.discard_data();\r\n\r\n  end = std::chrono::system_clock::now();\r\n  execution_time = end - start;\r\n  std::cout &lt;&lt; \"Make array_view: \" &lt;&lt; std::chrono::duration_cast&lt;std::chrono::microseconds&gt;(execution_time).count() \/ 1000.0 &lt;&lt; \" msec.\" &lt;&lt; std::endl;\r\n\r\n  start = std::chrono::system_clock::now();\r\n\r\n  concurrency::parallel_for_each(max_memory_gpu.get_default_view(), voxels_view.extent, [=](concurrency::index&lt;1&gt; idx) restrict(amp) {\r\n    bit_vertices_amp_view[idx] = (int)(voxels_view[idx] &lt; threshold);\r\n  });\r\n\r\n  end = std::chrono::system_clock::now();\r\n  execution_time = end - start;\r\n  std::cout &lt;&lt; \"GPU: \" &lt;&lt; std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(execution_time).count() &lt;&lt; \" msec.\" &lt;&lt; std::endl;\r\n\r\n  start = std::chrono::system_clock::now();\r\n\r\n  bit_vertices_amp_view.synchronize();\r\n\r\n  end = std::chrono::system_clock::now();\r\n  execution_time = end - start;\r\n  std::cout &lt;&lt; \"GPU -&gt; CPU: \" &lt;&lt; std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(execution_time).count() &lt;&lt; \" msec.\" &lt;&lt; std::endl;\r\n  \/\/ end C++ AMP array_view\r\n\r\n  \/\/ check Single CPU and C++ AMP array_view\r\n  bool check_amp = true;\r\n  i = 0;\r\n  for (const auto&amp; value : bit_vertices_amp) {\r\n    if (value != bit_vertices_single[i]) {\r\n      check_amp = false;\r\n      break;\r\n    }\r\n    ++i;\r\n  }\r\n  std::cout &lt;&lt; (check_amp ? \"OK\" : \"ERROR!!\") &lt;&lt; std::endl;\r\n\r\n  std::cout &lt;&lt; \"----------------\" &lt;&lt; std::endl;\r\n\r\n  \/\/ C++ AMP array\r\n  std::cout &lt;&lt; \"array: \" &lt;&lt; std::endl;\r\n\r\n  std::vector&lt;int&gt; bit_vertices_amp2(voxels.size());\r\n\r\n  start = std::chrono::system_clock::now();\r\n\r\n  concurrency::array&lt;int, 1&gt; voxels_array(voxels.size(), voxels.begin(), voxels.end(), max_memory_gpu.get_default_view());\r\n  concurrency::array&lt;int, 1&gt; bit_vertices_array(voxels.size(), max_memory_gpu.get_default_view());\r\n\r\n  end = std::chrono::system_clock::now();\r\n  execution_time = end - start;\r\n  std::cout &lt;&lt; \"Make array: \" &lt;&lt; std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(execution_time).count() &lt;&lt; \" msec.\" &lt;&lt; std::endl;\r\n\r\n  start = std::chrono::system_clock::now();\r\n\r\n  concurrency::parallel_for_each(max_memory_gpu.get_default_view(), voxels_array.extent, [=, &amp;voxels_array, &amp;bit_vertices_array](concurrency::index&lt;1&gt; idx) restrict(amp) {\r\n    bit_vertices_array[idx] = (int)(voxels_array[idx] &lt; threshold);\r\n  });\r\n\r\n  end = std::chrono::system_clock::now();\r\n  execution_time = end - start;\r\n  std::cout &lt;&lt; \"GPU: \" &lt;&lt; std::chrono::duration_cast&lt;std::chrono::microseconds&gt;(execution_time).count() \/ 1000.0 &lt;&lt; \" msec.\" &lt;&lt; std::endl;\r\n\r\n  start = std::chrono::system_clock::now();\r\n\r\n  bit_vertices_amp2 = bit_vertices_array;\r\n\r\n  end = std::chrono::system_clock::now();\r\n  execution_time = end - start;\r\n  std::cout &lt;&lt; \"GPU -&gt; CPU: \" &lt;&lt; std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(execution_time).count() &lt;&lt; \" msec.\" &lt;&lt; std::endl;\r\n  \/\/ end C++ AMP array\r\n\r\n  \/\/ check Single CPU and C++ AMP array\r\n  bool check_amp2 = true;\r\n  i = 0;\r\n  for (const auto&amp; value : bit_vertices_amp2) {\r\n    if (value != bit_vertices_single[i]) {\r\n      check_amp2 = false;\r\n      break;\r\n    }\r\n    ++i;\r\n  }\r\n  std::cout &lt;&lt; (check_amp2 ? \"OK\" : \"ERROR!!\") &lt;&lt; std::endl;\r\n\r\n  std::cout &lt;&lt; \"--------------------------------\" &lt;&lt; std::endl;\r\n\r\n  \/\/ CUDA\r\n  std::cout &lt;&lt; \"CUDA: \" &lt;&lt; std::endl;\r\n\r\n  std::vector&lt;int&gt; bit_vertices_cuda(voxels.size());\r\n\r\n  CUDA_make_bit_vertices(threshold, voxels, &amp;bit_vertices_cuda);\r\n  \/\/ end CUDA\r\n\r\n  \/\/ check Single CPU and CUDA\r\n  bool check_cuda = true;\r\n  i = 0;\r\n  for (const auto&amp; value : bit_vertices_cuda) {\r\n    if (value != bit_vertices_single[i]) {\r\n      check_cuda = false;\r\n      break;\r\n    }\r\n    ++i;\r\n  }\r\n  std::cout &lt;&lt; (check_cuda ? \"OK\" : \"ERROR!!\") &lt;&lt; std::endl;\r\n\r\n  std::cout &lt;&lt; \"--------------------------------\" &lt;&lt; std::endl;\r\n\r\n  return 0;\r\n}<\/pre>\n<pre class=\"lang:c++ decode:true \" title=\"CUDA_test.h\">\/\/ Copyright SCIEMENT, Inc.\r\n\/\/ by Hirofumi Seo, M.D., CEO &amp; President\r\n\r\n#pragma once\r\n\r\n#include \"cuda_runtime.h\"\r\n#include \"device_launch_parameters.h\"\r\n#include &lt;vector&gt;\r\n\r\ncudaError_t CUDA_make_bit_vertices(const int threshold, const std::vector&lt;int&gt;&amp; voxels, std::vector&lt;int&gt;* bit_vertices);<\/pre>\n<pre class=\"lang:c++ mark:14 decode:true \" title=\"CUDA_test.cu\">\/\/ Copyright SCIEMENT, Inc.\r\n\/\/ by Hirofumi Seo, M.D., CEO &amp; President\r\n\r\n#include \"CUDA_test.h\"\r\n#include &lt;chrono&gt;\r\n#include &lt;iostream&gt;\r\n#include &lt;stdio.h&gt;\r\n\r\n__global__ void Kernel_make_bit_vertices(const int threshold, const int* voxels, int* bit_vertices, const int voxels_size)\r\n{\r\n  int index = blockIdx.x * blockDim.x + threadIdx.x;\r\n  const int stride = blockDim.x * gridDim.x;\r\n  for (int i = index; i &lt; voxels_size; i += stride) {\r\n    bit_vertices[i] = (voxels[i] &lt; threshold) ? 1 : 0;\r\n  }\r\n}\r\n\r\ncudaError_t CUDA_make_bit_vertices(const int threshold, const std::vector&lt;int&gt;&amp; voxels, std::vector&lt;int&gt;* bit_vertices)\r\n{\r\n  int *dev_voxels = 0;\r\n  int *dev_bit_vertices = 0;\r\n  cudaError_t cudaStatus;\r\n\r\n  auto start = std::chrono::system_clock::now();\r\n\r\n  \/\/ Choose which GPU to run on, change this on a multi-GPU system.\r\n  cudaStatus = cudaSetDevice(0);\r\n  if (cudaStatus != cudaSuccess) {\r\n    fprintf(stderr, \"cudaSetDevice failed!  Do you have a CUDA-capable GPU installed?\");\r\n    goto Error;\r\n  }\r\n\r\n  auto end = std::chrono::system_clock::now();\r\n  auto execution_time = end - start;\r\n  std::cout &lt;&lt; \"Initialize: \" &lt;&lt; std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(execution_time).count() &lt;&lt; \" msec.\" &lt;&lt; std::endl;\r\n\r\n  const int voxels_size = voxels.size();\r\n  bit_vertices-&gt;resize(voxels_size);\r\n\r\n  start = std::chrono::system_clock::now();\r\n\r\n  \/\/ Allocate GPU buffers for two vectors (one input, one output).\r\n  cudaStatus = cudaMalloc((void**)&amp;dev_voxels, voxels_size * sizeof(int));\r\n  if (cudaStatus != cudaSuccess) {\r\n    fprintf(stderr, \"cudaMalloc failed!\");\r\n    goto Error;\r\n  }\r\n\r\n  cudaStatus = cudaMalloc((void**)&amp;dev_bit_vertices, voxels_size * sizeof(int));\r\n  if (cudaStatus != cudaSuccess) {\r\n    fprintf(stderr, \"cudaMalloc failed!\");\r\n    goto Error;\r\n  }\r\n\r\n  end = std::chrono::system_clock::now();\r\n  execution_time = end - start;\r\n  std::cout &lt;&lt; \"GPU Malloc: \" &lt;&lt; std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(execution_time).count() &lt;&lt; \" msec.\" &lt;&lt; std::endl;\r\n\r\n  start = std::chrono::system_clock::now();\r\n\r\n  \/\/ Copy input vector from host memory to GPU buffers.\r\n  cudaStatus = cudaMemcpy(dev_voxels, voxels.data(), voxels_size * sizeof(int), cudaMemcpyHostToDevice);\r\n  if (cudaStatus != cudaSuccess) {\r\n    fprintf(stderr, \"cudaMemcpy failed!\");\r\n    goto Error;\r\n  }\r\n\r\n  end = std::chrono::system_clock::now();\r\n  execution_time = end - start;\r\n  std::cout &lt;&lt; \"CPU -&gt; GPU: \" &lt;&lt; std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(execution_time).count() &lt;&lt; \" msec.\" &lt;&lt; std::endl;\r\n\r\n  start = std::chrono::system_clock::now();\r\n\r\n  \/\/ Launch a kernel on the GPU with one thread for each element.\r\n  const int block_size = 256; \/\/ MAX: 1024\r\n  const int num_blocks = (voxels_size + block_size - 1) \/ block_size;\r\n  Kernel_make_bit_vertices&lt;&lt;&lt;num_blocks, block_size&gt;&gt;&gt;(threshold, dev_voxels, dev_bit_vertices, voxels_size);\r\n  \r\n  \/\/ Check for any errors launching the kernel\r\n  cudaStatus = cudaGetLastError();\r\n  if (cudaStatus != cudaSuccess) {\r\n    fprintf(stderr, \"Kernel_make_bit_vertices launch failed: %s\\n\", cudaGetErrorString(cudaStatus));\r\n    goto Error;\r\n  }\r\n\r\n  \/\/ cudaDeviceSynchronize waits for the kernel to finish, and returns\r\n  \/\/ any errors encountered during the launch.\r\n  cudaStatus = cudaDeviceSynchronize();\r\n  if (cudaStatus != cudaSuccess) {\r\n    fprintf(stderr, \"cudaDeviceSynchronize returned error code %d after launching Kernel_make_bit_vertices!\\n\", cudaStatus);\r\n    goto Error;\r\n  }\r\n\r\n  end = std::chrono::system_clock::now();\r\n  execution_time = end - start;\r\n  std::cout &lt;&lt; \"GPU: \" &lt;&lt; std::chrono::duration_cast&lt;std::chrono::microseconds&gt;(execution_time).count() \/ 1000.0 &lt;&lt; \" msec.\" &lt;&lt; std::endl;\r\n\r\n  start = std::chrono::system_clock::now();\r\n\r\n  \/\/ Copy output vector from GPU buffer to host memory.\r\n  cudaStatus = cudaMemcpy(bit_vertices-&gt;data(), dev_bit_vertices, voxels_size * sizeof(int), cudaMemcpyDeviceToHost);\r\n  if (cudaStatus != cudaSuccess) {\r\n    fprintf(stderr, \"cudaMemcpy failed!\");\r\n    goto Error;\r\n  }\r\n\r\n  end = std::chrono::system_clock::now();\r\n  execution_time = end - start;\r\n  std::cout &lt;&lt; \"GPU -&gt; CPU: \" &lt;&lt; std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(execution_time).count() &lt;&lt; \" msec.\" &lt;&lt; std::endl;\r\n\r\nError:\r\n  cudaFree(dev_voxels);\r\n  cudaFree(dev_bit_vertices);\r\n\r\n  return cudaStatus;\r\n}<\/pre>\n<p><strong>\u25c6\u5b9f\u884c\u7d50\u679c<\/strong><br \/>\n<strong>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br \/>\nSingle CPU: 10 msec.<br \/>\n&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br \/>\nPPL: 8 msec.<br \/>\nOK<br \/>\n&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br \/>\nC++ AMP: <font color=\"red\">Initialize: 49 msec.<\/font><br \/>\narray_view:<br \/>\nMake array_view: 0.036 msec.<br \/>\nGPU: 13 msec.<br \/>\nGPU -&gt; CPU: 12 msec.<br \/>\nOK<br \/>\n&#8212;&#8212;&#8212;&#8212;&#8212;-<br \/>\narray:<br \/>\nMake array: 9 msec.<br \/>\nGPU: 0.142 msec.<br \/>\n<font color=\"red\">GPU -&gt; CPU: 28 msec.<\/font><br \/>\nOK<br \/>\n&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br \/>\nCUDA:<br \/>\n<font color=\"red\">Initialize: 170 msec.<\/font><br \/>\n<font color=\"red\">GPU Malloc: 99 msec.<\/font><br \/>\nCPU -&gt; GPU: 9 msec.<br \/>\nGPU: 0.622 msec.<br \/>\nGPU -&gt; CPU: 9 msec.<br \/>\nOK<br \/>\n&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<\/strong><\/p>\n<p>\u306a\u3093\u3068\u3044\u3046\u3053\u3068\u3067\u3057\u3087\u3046\u3002<strong>\u3053\u308c\u304f\u3089\u3044\u306e\u5358\u7d14\u306a\u51e6\u7406\u306e\u5834\u5408\u30011000\u4e07\u4ee5\u4e0a\u306e\u8981\u7d20\u304c\u3042\u3063\u3066\u3082\u30b7\u30f3\u30b0\u30ebCPU\u51e6\u7406\u3068\u30de\u30eb\u30c1\u30b9\u30ec\u30c3\u30c9CPU\u51e6\u7406\u3067\u305d\u3053\u307e\u3067\u51e6\u7406\u6642\u9593\u304c\u5909\u308f\u3089<\/strong>\u305a\u3001<strong>GPGPU\u306b\u3088\u308b\u4e26\u5217\u5316\u306fCPU, GPU\u9593\u306e\u30e1\u30e2\u30ea\u79fb\u52d5\u304c\u3069\u3046\u3057\u3088\u3046\u3082\u306a\u304f\u30dc\u30c8\u30eb\u30cd\u30c3\u30af\u306b\u306a\u3063\u3066\u3044\u307e\u3059<\/strong>\u3002<br \/>\n\u307e\u305f\u3001<strong>GPGPU\u306e\u5834\u5408\u306fC++ AMP\u306b\u3057\u308dCUDA\u306b\u3057\u308d\u3001\u521d\u671f\u5316\u306e\u6642\u9593\u304c\u305d\u3053\u305d\u3053\u3042\u308a<\/strong>\u3001<strong>CUDA\u306b\u81f3\u3063\u3066\u306fGPU\u4e0a\u306e\u30e1\u30e2\u30ea\u78ba\u4fdd\u304c\u6050\u308d\u3057\u304f\u9045\u3044<\/strong>\u3001\u3068\u3044\u3046\u3053\u3068\u304c\u308f\u304b\u308a\u307e\u3057\u305f\u3002<\/p>\n<p><strong>\u4eca\u56de\u306e\u3088\u3046\u306a\u6975\u3081\u3066\u5358\u7d14\u306a\u51e6\u7406\u306e\u5834\u5408\u3001\u51e6\u7406\u3092\u3057\u305f\u7d50\u679c\u3092CPU\u5074\u3067\u7528\u3044\u3001\u4e14\u3064\u3001\u305d\u306e\u51e6\u7406\u306f\u4e00\u5ea6\u3057\u304b\u884c\u308f\u308c\u306a\u3044\u3088\u3046\u306a\u5834\u5408\u306b\u306f\u3001\u308f\u3056\u308f\u3056\u60aa\u6226\u82e6\u95d8\u3057\u3066CPU\u30de\u30eb\u30c1\u30b9\u30ec\u30c3\u30c9\u5316\u3084GPGPU\u5316\u3092\u3057\u305f\u3068\u3053\u308d\u3067\u307b\u3068\u3093\u3069\u5909\u308f\u3089\u306a\u3044\u304b\u3001\u5927\u5e45\u306b\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u304c\u843d\u3061\u3066\u3057\u307e\u3044\u3001\u5168\u304f\u610f\u5473\u304c\u306a\u3044<\/strong>\u3068\u3044\u3046\u7d50\u8ad6\u306b\u306a\u308a\u307e\u3057\u305f\u3002<\/p>\n<p>C++ AMP\u306earray_view\u3068array\u3068\u3067\u8a08\u7b97\u6642\u9593\u306b\u3053\u3053\u307e\u3067\u5dee\u304c\u51fa\u308b\u7406\u7531\u306f\u826f\u304f\u308f\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u2026\u3002array_view\u306e\u5834\u5408\u306f\u30ab\u30fc\u30cd\u30eb\u95a2\u6570\u5b9f\u884c\u6642\u306b\u521d\u3081\u3066CPU -&gt; GPU\u3078\u306e\u30e1\u30e2\u30ea\u8ee2\u9001\u304c\u884c\u308f\u308c\u308b\u3068\u306e\u3053\u3068\u306a\u306e\u3067\u3001\u305d\u308c\u3092\u8003\u616e\u3059\u308b\u3068<\/p>\n<p><strong>array_view:<br \/>\nGPU: 13 msec.<\/strong><\/p>\n<p>\u306fCPU -&gt; GPU\u3068GPU\u4e0a\u3067\u306e\u8a08\u7b97\u3092\u5408\u308f\u305b\u305f\u6642\u9593\u304c13 msec\u3068\u8003\u3048\u308b\u306e\u304c\u826f\u3044\u306e\u3060\u3068\u601d\u3044\u307e\u3059\u304c\u3001array\u306e\u5834\u5408\u306bGPU -&gt; CPU\u3078\u306e\u8ee2\u9001\u306b28 msec\u3082\u304b\u304b\u308b\u306e\u306f\u9a5a\u304d\u3067\u3057\u305f\u3002<\/p>\n<p>\u4eca\u56de\u306e\u3088\u3046\u306b\u3001\u30d4\u30af\u30bb\u30eb\uff08\u30dc\u30af\u30bb\u30eb\uff09\u306e\u5024\u304c\u4e0d\u5909\u306e\u5834\u5408\u306b\u306f\u3001\u6700\u521d\u306bCPU -&gt; GPU\u306b\u30c7\u30fc\u30bf\u3092\u8ee2\u9001\u3057\u3066\u3057\u307e\u3048\u3070\u305d\u306e\u30c7\u30fc\u30bf\u3092\u66f4\u65b0\u3059\u308b\u5fc5\u8981\u306f\u3042\u308a\u307e\u305b\u3093\u304a\u3067\u3001\u3082\u3057\u95be\u5024\u304c\u8272\u3005\u5909\u308f\u308b\u3053\u3068\u3067\u7e70\u308a\u8fd4\u3057\u3053\u306e\u4e8c\u5024\u5316\u51e6\u7406\u3092\u884c\u3046\u306e\u3067\u3042\u308c\u3070\u3001<br \/>\nCUDA\u306e\u5834\u5408\u306f<\/p>\n<p><strong>CUDA:<br \/>\nGPU: 0.622 msec.<br \/>\nGPU -&gt; CPU: 9 msec.<\/strong><\/p>\n<p>\u306e\u5408\u8a08\u6642\u9593\u3001\u3064\u307e\u308a\u7d049.6 msec\u3068\u3057\u3066\u8a55\u4fa1\u3059\u308c\u3070\u826f\u3044\u306e\u3067\u3059\u304c\u3001GPU\u4e0a\u3067\u306e\u8a08\u7b97\u306f0.6 msec\u3068\u7206\u901f\u306a\u306e\u306b\u3082\u304b\u304b\u308f\u3089\u305a\u3001GPU -&gt; CPU\u3078\u306e\u30c7\u30fc\u30bf\u8ee2\u9001\u306b9 msec\u3082\u304b\u304b\u3063\u3066\u3057\u307e\u3044\u3001\u30b7\u30f3\u30b0\u30ebCPU\u51e6\u7406\u3068\u307b\u307c\u5909\u308f\u3089\u306a\u3044\u3068\u3044\u3046\u3068\u3066\u3082\u6b8b\u5ff5\u306a\u7d50\u679c\u306b\u306a\u3063\u3066\u3057\u307e\u3044\u307e\u3057\u305f\u3002<\/p>\n<p>\u4e26\u5217\u51e6\u7406\u51fa\u6765\u308b\u304b\u3089\u3068\u8a00\u3063\u3066\u3001\u3044\u3064\u4f55\u6642\u3067\u3082CPU\u30de\u30eb\u30c1\u30b9\u30ec\u30c3\u30c9\u5316\u3084GPGPU\u5316\u3092\u3057\u305f\u307b\u3046\u304c\u901f\u3044\u3068\u3082\u9650\u308a\u307e\u305b\u3093\u306d\u3002\u3082\u3063\u3068\u8fbc\u307f\u5165\u3063\u305f\u8a08\u7b97\u3092\u3059\u308b\u3068\u304d\u306a\u3069\u3001\u30e1\u30e2\u30ea\u9593\u306e\u30c7\u30fc\u30bf\u8ee2\u9001\u6642\u9593\u304c\u6c17\u306b\u306a\u3089\u306a\u3044\u304f\u3089\u3044\u306e\u51e6\u7406\u3092\u3059\u308b\u3068\u304d\u306b\u521d\u3081\u3066\u4e26\u5217\u51e6\u7406\u306e\u5f37\u307f\u304c\u6d3b\u304b\u3055\u308c\u305d\u3046\u3067\u3059\u3002<\/p>\n<hr \/>\n<p>\u203b\u672c\u8a18\u4e8b\u5185\u5bb9\u306f\u3001\u56fd\u7acb\u7814\u7a76\u958b\u767a\u6cd5\u4eba \u65e5\u672c\u533b\u7642\u7814\u7a76\u958b\u767a\u6a5f\u69cb\uff08AMED\uff09\u306e<a href=\"https:\/\/www.amed.go.jp\/koubo\/02\/01\/0201C_00124.html\" rel=\"noopener\" target=\"_blank\">\u5e73\u621029\u5e74\u5ea6 \u300c\u672a\u6765\u533b\u7642\u3092\u5b9f\u73fe\u3059\u308b\u533b\u7642\u6a5f\u5668\u30fb\u30b7\u30b9\u30c6\u30e0\u7814\u7a76\u958b\u767a\u4e8b\u696d\u300e\u8853\u4e2d\u306e\u8fc5\u901f\u306a\u5224\u65ad\u30fb\u6c7a\u5b9a\u3092\u652f\u63f4\u3059\u308b\u305f\u3081\u306e\u8a3a\u65ad\u652f\u63f4\u6a5f\u5668\u30fb\u30b7\u30b9\u30c6\u30e0\u958b\u767a\u300f\u300d\u63a1\u629e\u8ab2\u984c<\/a>\u3067\u3042\u308b\u300c\u8853\u524d\u3068\u8853\u4e2d\u3092\u3064\u306a\u3050\u30b9\u30de\u30fc\u30c8\u624b\u8853\u30ac\u30a4\u30c9\u30bd\u30d5\u30c8\u30a6\u30a7\u30a2\u306e\u958b\u767a\u300d\uff08\u4ee3\u8868\u6a5f\u95a2\u540d\uff1a\u6771\u4eac\u5927\u5b66\u3001\u7814\u7a76\u958b\u767a\u4ee3\u8868\u8005\u540d\uff1a\u9f4a\u85e4\u5ef6\u4eba\uff09\u306b\u3001\u6771\u4eac\u5927\u5b66\u5927\u5b66\u9662\u60c5\u5831\u7406\u5de5\u5b66\u7cfb\u7814\u7a76\u79d1\u306e\u5b66\u8853\u652f\u63f4\u5c02\u9580\u8077\u54e1\u3068\u3057\u3066\u53c2\u753b\u3057\u3066\u3044\u308b\u702c\u5c3e\u62e1\u53f2\u304c\u3001\u7814\u7a76\u958b\u767a\u3068\u3057\u3066\u884c\u3063\u3066\u3044\u308b\u3082\u306e\u3084\u305d\u306e\u6210\u679c\u3092\u4e00\u90e8\u542b\u3093\u3067\u3044\u307e\u3059\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u753b\u50cf\u51e6\u7406\u306e\u5206\u91ce\u306b\u304a\u3044\u3066\u3001\u5404\u30d4\u30af\u30bb\u30eb\uff08\u7a7a\u9593\u306e\u5834\u5408\u306f\u5404\u30dc\u30af\u30bb\u30eb\uff09\u306e\u5024\u30920\u304b1\u304b\u306e\u3069\u3061\u3089\u304b\u306e\u5024\u306b\u5206\u3051\u308b\u4e8c\u5024\u5316\u51e6\u7406\u304c\u983b\u7e41\u306b\u884c\u308f\u308c\u307e\u3059\u3002 \u4f55\u3092\u4ee5\u30660\u307e\u305f\u306f1\u3068\u3059\u308b\u304b\u304c\u30dd\u30a4\u30f3\u30c8\u306a\u308f\u3051\u3067\u3059\u304c\u3001\u3053\u3053\u3067\u306f\u8d85\u7c21\u5358\u306b\u3001\u95be\u5024\uff08threshold &#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,8,5,7],"tags":[],"class_list":["post-110","post","type-post","status-publish","format-standard","hentry","category-c","category-c-amp","category-cuda","category-ppl"],"_links":{"self":[{"href":"https:\/\/www.sciement.com\/tech-blog\/wp-json\/wp\/v2\/posts\/110","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.sciement.com\/tech-blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sciement.com\/tech-blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sciement.com\/tech-blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sciement.com\/tech-blog\/wp-json\/wp\/v2\/comments?post=110"}],"version-history":[{"count":20,"href":"https:\/\/www.sciement.com\/tech-blog\/wp-json\/wp\/v2\/posts\/110\/revisions"}],"predecessor-version":[{"id":190,"href":"https:\/\/www.sciement.com\/tech-blog\/wp-json\/wp\/v2\/posts\/110\/revisions\/190"}],"wp:attachment":[{"href":"https:\/\/www.sciement.com\/tech-blog\/wp-json\/wp\/v2\/media?parent=110"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sciement.com\/tech-blog\/wp-json\/wp\/v2\/categories?post=110"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sciement.com\/tech-blog\/wp-json\/wp\/v2\/tags?post=110"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}