Skip to content
Snippets Groups Projects
Commit 86a6112e authored by Markus Holzer's avatar Markus Holzer
Browse files

Fuse thread safety check with existing check

parent 3633e4c2
No related merge requests found
Pipeline #66462 failed with stages
in 4 minutes and 47 seconds
...@@ -135,14 +135,9 @@ class CreateKernelConfig: ...@@ -135,14 +135,9 @@ class CreateKernelConfig:
""" """
skip_independence_check: bool = False skip_independence_check: bool = False
""" """
Don't check that loop iterations are independent. This is needed e.g. for By default the assignment list is checked for read/write independence. This means fields are only written at
periodicity kernel, that access the field outside the iteration bounds. Use with care! locations where they are read. Doing so guarantees thread safety. In some cases e.g. for
""" periodicity kernel, this can not be assured and does the check needs to be deactivated. Use with care!
check_thread_safety: bool = True
"""
Assignments are considered thread safe if read and writes only target the same locations. If this is not the case,
multithreaded optimisations will fail. The thread safety check can be deactivated to use e.g. GPUs anyway.
Use with care!
""" """
class DataTypeFactory: class DataTypeFactory:
......
...@@ -43,7 +43,6 @@ class KernelConstraintsCheck: ...@@ -43,7 +43,6 @@ class KernelConstraintsCheck:
self.fields_read = set() self.fields_read = set()
self.check_independence_condition = check_independence_condition self.check_independence_condition = check_independence_condition
self.check_double_write_condition = check_double_write_condition self.check_double_write_condition = check_double_write_condition
self.thread_safe = True
def visit(self, obj): def visit(self, obj):
if isinstance(obj, (AssignmentCollection, NodeCollection)): if isinstance(obj, (AssignmentCollection, NodeCollection)):
...@@ -117,7 +116,9 @@ class KernelConstraintsCheck: ...@@ -117,7 +116,9 @@ class KernelConstraintsCheck:
if fai in self.field_reads: if fai in self.field_reads:
reads = tuple(self.field_reads[fai]) reads = tuple(self.field_reads[fai])
if len(reads) > 1 or lhs.offsets != reads[0]: if len(reads) > 1 or lhs.offsets != reads[0]:
self.thread_safe = False if self.check_independence_condition:
raise ValueError(f"Field {lhs.field.name} is written at different location than it was read. "
f"This means the resulting kernel would not be thread safe")
elif isinstance(lhs, sp.Symbol): elif isinstance(lhs, sp.Symbol):
if self.scopes.is_defined_locally(lhs): if self.scopes.is_defined_locally(lhs):
raise ValueError(f"Assignments not in SSA form, multiple assignments to {lhs.name}") raise ValueError(f"Assignments not in SSA form, multiple assignments to {lhs.name}")
......
...@@ -130,12 +130,6 @@ def create_domain_kernel(assignments: NodeCollection, *, config: CreateKernelCon ...@@ -130,12 +130,6 @@ def create_domain_kernel(assignments: NodeCollection, *, config: CreateKernelCon
check_double_write_condition=not config.allow_double_writes) check_double_write_condition=not config.allow_double_writes)
check.visit(assignments) check.visit(assignments)
if not check.thread_safe and config.check_thread_safety:
base = "Assignments are not thread safe because data is read and written on different locations."
if config.cpu_openmp:
raise ValueError(f"{base} OpenMP optimisation is not permitted in this scenario.")
if config.target == Target.GPU:
raise ValueError(f"{base} GPU target is not permitted in this case, only CPU target with single thread")
assignments.bound_fields = check.fields_written assignments.bound_fields = check.fields_written
assignments.rhs_fields = check.fields_read assignments.rhs_fields = check.fields_read
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment