Skip to content
This repository was archived by the owner on Mar 28, 2023. It is now read-only.

[SYCL] Add tests for sycl-sanitize tool #459

Draft
wants to merge 3 commits into
base: intel
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,9 @@ SYCL/BFloat16 @AlexeySotkin @MrSidims

# Deprecated features
SYCL/DeprecatedFeatures @intel/llvm-reviewers-runtime

# XPTI and XPTI Framework
SYCL/XPTI @tovinkere @andykaylor @alexbatashev

# Additional SYCL tools
SYCL/Tools @intel/llvm-reviewers-runtime
27 changes: 27 additions & 0 deletions SYCL/Tools/sanitize_buffer_device_ptr.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// REQUIRES: sycl-sanitizer
// RUN: %clangxx -fsycl -fsycl-unnamed-lambda -fsycl-targets=%sycl_triple %s -o %t.out
// RUN: %CPU_RUN_PLACEHOLDER not sycl-sanitizer %t.out %CPU_CHECK_PLACEHOLDER

#include <sycl/sycl.hpp>

int main() {
sycl::queue Q{sycl::default_selector()};

int *Ptr = sycl::malloc_device<int>(200, Q);

sycl::buffer<int> Buf(Ptr, sycl::range{200},
sycl::property::buffer::use_host_ptr());

Q.submit([&](sycl::handler &CGH) {
sycl::accessor Acc{Buf, CGH, sycl::write_only};
CGH.parallel_for(sycl::range{200}, [=](const auto I) { Acc[I] = 1; });
});

Q.wait();

return 0;
}

// CHECK: Attempt to construct a buffer with non-host pointer.
// CHECK-NEXT: Allocation location: function main at <unknown>:10
// CHECK-NEXT: Buffer location: function <unknown> at <unknown>:0
27 changes: 27 additions & 0 deletions SYCL/Tools/sanitize_buffer_host_small_ptr.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// REQUIRES: sycl-sanitizer
// RUN: %clangxx -fsycl -fsycl-unnamed-lambda -fsycl-targets=%sycl_triple %s -o %t.out
// RUN: %CPU_RUN_PLACEHOLDER not sycl-sanitizer %t.out %CPU_CHECK_PLACEHOLDER

#include <sycl/sycl.hpp>

int main() {
sycl::queue Q{sycl::default_selector()};

int *Ptr = sycl::malloc_host<int>(100, Q);

sycl::buffer<int> Buf(Ptr, sycl::range{200},
sycl::property::buffer::use_host_ptr());

Q.submit([&](sycl::handler &CGH) {
sycl::accessor Acc{Buf, CGH, sycl::write_only};
CGH.parallel_for(sycl::range{200}, [=](const auto I) { Acc[I] = 1; });
});

Q.wait();

return 0;
}

// CHECK: Buffer size exceeds allocated host memory size.
// CHECK-NEXT: Allocation location: function main at <unknown>:10
// CHECK-NEXT: Buffer location: function <unknown> at <unknown>:0
23 changes: 23 additions & 0 deletions SYCL/Tools/sanitize_memleak.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// REQUIRES: sycl-sanitizer
// RUN: %clangxx -fsycl -fsycl-targets=%sycl_triple %s -o %t.out
// RUN: %CPU_RUN_PLACEHOLDER not sycl-sanitizer %t.out %CPU_CHECK_PLACEHOLDER

#include <sycl/sycl.hpp>

int main() {
sycl::queue Q{sycl::default_selector()};

sycl::malloc_device(100, Q);
sycl::malloc_host(100, Q);
sycl::malloc_shared(100, Q);

return 0;
}

// CHECK: Found 3 leaked memory allocations
// CHECK-NEXT: Leaked pointer: 0x7f8070000000
// CHECK-NEXT: Location: function main at <unknown>:12
// CHECK-NEXT: Leaked pointer: 0x7f8076c00000
// CHECK-NEXT: Location: function main at <unknown>:10
// CHECK-NEXT: Leaked pointer: 0x7f8076e00000
// CHECK-NEXT: Location: function main at <unknown>:11
128 changes: 128 additions & 0 deletions SYCL/XPTI/Inputs/test_collector.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#include "xpti/xpti_trace_framework.hpp"

#include <iostream>
#include <mutex>
#include <string_view>

std::mutex GMutex;

XPTI_CALLBACK_API void syclCallback(uint16_t,
xpti::trace_event_data_t *,
xpti::trace_event_data_t *,
uint64_t, const void *);
XPTI_CALLBACK_API void syclPiCallback(uint16_t,
xpti::trace_event_data_t *,
xpti::trace_event_data_t *,
uint64_t, const void *);

XPTI_CALLBACK_API void xptiTraceInit(unsigned int MajorVersion,
unsigned int MinorVersion,
const char *VersionStr,
const char *StreamName) {
std::cout << "xptiTraceInit: Stream Name = " << StreamName << "\n";
std::string_view NameView{StreamName};

if (NameView == "sycl.pi") {
uint8_t StreamID = xptiRegisterStream(StreamName);
xptiRegisterCallback(
StreamID, static_cast<uint16_t>(xpti::trace_point_type_t::function_begin),
syclPiCallback);
xptiRegisterCallback(
StreamID, static_cast<uint16_t>(xpti::trace_point_type_t::function_with_args_end),
syclPiCallback);
}
if (NameView == "sycl") {
uint8_t StreamID = xptiRegisterStream(StreamName);
xptiRegisterCallback(StreamID,
static_cast<uint16_t>(xpti::trace_point_type_t::graph_create),
syclCallback);
xptiRegisterCallback(
StreamID, static_cast<uint16_t>(xpti::trace_point_type_t::node_create), syclCallback);
xptiRegisterCallback(
StreamID, static_cast<uint16_t>(xpti::trace_point_type_t::edge_create), syclCallback);
xptiRegisterCallback(
StreamID, static_cast<uint16_t>(xpti::trace_point_type_t::task_begin), syclCallback);
xptiRegisterCallback(
StreamID, static_cast<uint16_t>(xpti::trace_point_type_t::task_end), syclCallback);
xptiRegisterCallback(
StreamID, static_cast<uint16_t>(xpti::trace_point_type_t::signal), syclCallback);
xptiRegisterCallback(StreamID,
static_cast<uint16_t>(xpti::trace_point_type_t::barrier_begin),
syclCallback);
xptiRegisterCallback(
StreamID, static_cast<uint16_t>(xpti::trace_point_type_t::barrier_end), syclCallback);
xptiRegisterCallback(
StreamID, static_cast<uint16_t>(xpti::trace_point_type_t::wait_begin), syclCallback);
xptiRegisterCallback(
StreamID, static_cast<uint16_t>(xpti::trace_point_type_t::wait_end), syclCallback);
xptiRegisterCallback(StreamID, static_cast<uint16_t>(xpti::trace_point_type_t::signal),
syclCallback);
}
}

XPTI_CALLBACK_API void xptiTraceFinish(const char *streamName) {
std::cout << "xptiTraceFinish: Stream Name = " << streamName << "\n";
}

XPTI_CALLBACK_API void syclPiCallback(uint16_t TraceType,
xpti::trace_event_data_t *,
xpti::trace_event_data_t *,
uint64_t, const void *UserData) {
std::lock_guard Lock{GMutex};
auto Type = static_cast<xpti::trace_point_type_t>(TraceType);
const char *funcName = static_cast<const char*>(UserData);
if (Type == xpti::trace_point_type_t::function_begin) {
std::cout << "PI Call Begin : ";
} else if (Type == xpti::trace_point_type_t::function_end){
std::cout << "PI Call End : ";
}
std::cout << funcName << "\n";
}

XPTI_CALLBACK_API void syclCallback(uint16_t TraceType,
xpti::trace_event_data_t *,
xpti::trace_event_data_t *Event,
uint64_t, const void *UserData) {
std::lock_guard Lock{GMutex};
auto Type = static_cast<xpti::trace_point_type_t>(TraceType);
switch (Type) {
case xpti::trace_point_type_t::graph_create:
std::cout << "Graph create\n";
break;
case xpti::trace_point_type_t::node_create:
std::cout << "Node create\n";
break;
case xpti::trace_point_type_t::edge_create:
std::cout << "Edge create\n";
break;
case xpti::trace_point_type_t::task_begin:
std::cout << "Task begin\n";
break;
case xpti::trace_point_type_t::task_end:
std::cout << "Task end\n";
break;
case xpti::trace_point_type_t::signal:
std::cout << "Signal\n";
break;
case xpti::trace_point_type_t::wait_begin:
std::cout << "Wait begin\n";
break;
case xpti::trace_point_type_t::wait_end:
std::cout << "Wait end\n";
break;
case xpti::trace_point_type_t::barrier_begin:
std::cout << "Barrier begin\n";
break;
case xpti::trace_point_type_t::barrier_end:
std::cout << "Barrier end\n";
break;
default:
std::cout << "Unknown tracepoint\n";
}

xpti::metadata_t *Metadata = xptiQueryMetadata(Event);
for (auto &Item : *Metadata) {
std::cout << " " << xptiLookupString(Item.first)
<< " : " << xptiLookupString(Item.second) << "\n";
}
}
179 changes: 179 additions & 0 deletions SYCL/XPTI/basic_event_collection.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
// REQUIRES: xptifw
// RUN: %clangxx -fsycl %s -DXPTI_COLLECTOR -shared -fPIC -std=c++17 -o %t_collector.dll -lxptifw
// RUN: %clangxx -fsycl -fsycl-unnamed-lambda -fsycl-targets=%sycl_triple %s -o %t.out
// RUN: env XPTI_TRACE_ENABLED=1 env XPTI_FRAMEWORK_DISPATCHER=%xptifw_lib env XPTI_SUBSCRIBERS=%t_collector.dll %CPU_RUN_PLACEHOLDER %t %CPU_CHECK_PLACEHOLDER

#ifdef XPTI_COLLECTOR

#include "Inputs/test_collector.cpp"

#else

#include <sycl/sycl.hpp>

int main() {
sycl::queue Q{sycl::default_selector{}};

auto Ptr = sycl::malloc_device<int>(1, Q);

auto Evt1 = Q.single_task([=]() {
Ptr[0] = 1;
});

auto Evt2 = Q.submit([&](sycl::handler &CGH) {
CGH.depends_on(Evt1);
CGH.single_task([=]() {
Ptr[0]++;
});
});

Evt2.wait();

int Res = 0;
Q.memcpy(&Res, Ptr, 1);
Q.wait();

assert(Res == 2);

return 0;
}

#endif

// CHECK: xptiTraceInit: Stream Name = sycl
// CHECK-NEXT: Graph create
// CHECK-NEXT: xptiTraceInit: Stream Name = sycl.pi
// CHECK-NEXT: xptiTraceInit: Stream Name = sycl.pi.debug
// CHECK-NEXT: PI Call Begin : piPlatformsGet
// CHECK-NEXT: PI Call Begin : piPlatformsGet
// CHECK-NEXT: PI Call Begin : piDevicesGet
// CHECK-NEXT: PI Call Begin : piDevicesGet
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piDeviceRetain
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piPlatformGetInfo
// CHECK-NEXT: PI Call Begin : piPlatformGetInfo
// CHECK-NEXT: PI Call Begin : piDeviceRelease
// CHECK-NEXT: PI Call Begin : piDevicesGet
// CHECK-NEXT: PI Call Begin : piDevicesGet
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piDevicesGet
// CHECK-NEXT: PI Call Begin : piDevicesGet
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piDevicesGet
// CHECK-NEXT: PI Call Begin : piDevicesGet
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piDeviceRetain
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piDevicesGet
// CHECK-NEXT: PI Call Begin : piDevicesGet
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piContextCreate
// CHECK-NEXT: PI Call Begin : piQueueCreate
// CHECK-NEXT: PI Call Begin : piextUSMDeviceAlloc
// CHECK-NEXT: PI Call Begin : piextDeviceSelectBinary
// CHECK-NEXT: Node create
// CHECK-NEXT: from_source : false
// CHECK-NEXT: kernel_name :
// CHECK-NEXT: sycl_device : CPU
// CHECK-NEXT: Task begin
// CHECK-NEXT: from_source : false
// CHECK-NEXT: kernel_name :
// CHECK-NEXT: sycl_device : CPU
// CHECK-NEXT: PI Call Begin : piextDeviceSelectBinary
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piPlatformGetInfo
// CHECK-NEXT: PI Call Begin : piPlatformGetInfo
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piPlatformGetInfo
// CHECK-NEXT: PI Call Begin : piPlatformGetInfo
// CHECK-NEXT: PI Call Begin : piProgramCreate
// CHECK-NEXT: PI Call Begin : piProgramBuild
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piDeviceGetInfo
// CHECK-NEXT: PI Call Begin : piPlatformGetInfo
// CHECK-NEXT: PI Call Begin : piPlatformGetInfo
// CHECK-NEXT: PI Call Begin : piKernelCreate
// CHECK-NEXT: PI Call Begin : piKernelSetExecInfo
// CHECK-NEXT: PI Call Begin : piextKernelSetArgPointer
// CHECK-NEXT: PI Call Begin : piKernelGetGroupInfo
// CHECK-NEXT: PI Call Begin : piEnqueueKernelLaunch
// CHECK-NEXT: Signal
// CHECK-NEXT: from_source : false
// CHECK-NEXT: kernel_name :
// CHECK-NEXT: sycl_device : CPU
// CHECK-NEXT: Task end
// CHECK-NEXT: from_source : false
// CHECK-NEXT: kernel_name :
// CHECK-NEXT: sycl_device : CPU
// CHECK-NEXT: PI Call Begin : piextDeviceSelectBinary
// CHECK-NEXT: Node create
// CHECK-NEXT: from_source : false
// CHECK-NEXT: kernel_name :
// CHECK-NEXT: sycl_device : CPU
// CHECK-NEXT: Node create
// CHECK-NEXT: kernel_name : virtual_node
// CHECK-NEXT: Edge create
// CHECK-NEXT: event : Event
// CHECK-NEXT: kernel_name : virtual_node
// CHECK-NEXT: Task begin
// CHECK-NEXT: from_source : false
// CHECK-NEXT: kernel_name :
// CHECK-NEXT: sycl_device : CPU
// CHECK-NEXT: PI Call Begin : piKernelCreate
// CHECK-NEXT: PI Call Begin : piKernelSetExecInfo
// CHECK-NEXT: PI Call Begin : piextKernelSetArgPointer
// CHECK-NEXT: PI Call Begin : piKernelGetGroupInfo
// CHECK-NEXT: PI Call Begin : piEnqueueKernelLaunch
// CHECK-NEXT: Signal
// CHECK-NEXT: from_source : false
// CHECK-NEXT: kernel_name :
// CHECK-NEXT: sycl_device : CPU
// CHECK-NEXT: Task end
// CHECK-NEXT: from_source : false
// CHECK-NEXT: kernel_name :
// CHECK-NEXT: sycl_device : CPU
// CHECK-NEXT: Wait begin
// CHECK-NEXT: PI Call Begin : piEventsWait
// CHECK-NEXT: Wait end
// CHECK-NEXT: PI Call Begin : piextUSMEnqueueMemcpy
// CHECK-NEXT: PI Call Begin : piEventRelease
// CHECK-NEXT: Wait begin
// CHECK-NEXT: sym_line_no : 34
// CHECK-NEXT: sym_function_name : main
// CHECK-NEXT: sycl_device : CPU
// CHECK-NEXT: PI Call Begin : piQueueFinish
// CHECK-NEXT: Wait end
// CHECK-NEXT: sym_line_no : 34
// CHECK-NEXT: sym_function_name : main
// CHECK-NEXT: sycl_device : CPU
// CHECK-NEXT: PI Call Begin : piEventRelease
// CHECK-NEXT: PI Call Begin : piEventRelease
// CHECK-NEXT: PI Call Begin : piQueueRelease
// CHECK-NEXT: PI Call Begin : piContextRelease
// CHECK-NEXT: PI Call Begin : piKernelRelease
// CHECK-NEXT: PI Call Begin : piKernelRelease
// CHECK-NEXT: PI Call Begin : piProgramRelease
// CHECK-NEXT: PI Call Begin : piDeviceRelease
// CHECK-NEXT: PI Call Begin : piTearDown
// CHECK-NEXT: xptiTraceFinish: Stream Name = sycl.pi
// CHECK-NEXT: xptiTraceFinish: Stream Name = sycl.pi.debug
// CHECK-NEXT: xptiTraceFinish: Stream Name = sycl
Loading