Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove usages of std::call_once. #5599

Merged
merged 5 commits into from
Aug 8, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
17 changes: 7 additions & 10 deletions dali/c_api/c_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,6 @@ typedef daliPipelineHandle *daliPipelineHandle_t;

namespace {

bool dali_initialized = false;

int PopCurrBatchSize(batch_size_map_t *batch_size_map, int max_batch_size,
const std::string &op_name) {
auto it = batch_size_map->find(op_name);
Expand Down Expand Up @@ -222,14 +220,13 @@ inline std::unique_ptr<DALIPipeline> WrapPipeline(std::unique_ptr<dali::Pipeline


void daliInitialize() {
static std::once_flag init_flag;
auto init = [&] {
dali::DALIInit(dali::OpSpec("CPUAllocator"),
dali::OpSpec("PinnedCPUAllocator"),
dali::OpSpec("GPUAllocator"));
dali_initialized = true;
};
std::call_once(init_flag, init);
static int init = []() {
dali::DALIInit(dali::OpSpec("CPUAllocator"),
dali::OpSpec("PinnedCPUAllocator"),
dali::OpSpec("GPUAllocator"));
return 0;
}();
(void)init;
}


Expand Down
74 changes: 74 additions & 0 deletions dali/core/call_once_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
//
// 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
//
// 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.

#include <gtest/gtest.h>
#include <atomic>
#include <thread>
#include <vector>
#include "dali/core/call_once.h"

namespace dali {

TEST(CallOnce, CountCalls) {
dali::once_flag once;
std::atomic_int calls{0};
std::vector<std::thread> threads;
for (int i = 0; i < 100; i++) {
threads.emplace_back([&]() {
dali::call_once(once, [&]() {
++calls;
});
});
}
for (auto &t : threads)
t.join();
EXPECT_EQ(calls.load(), 1);
}

TEST(CallOnce, RetryOnThrow) {
dali::once_flag once;
std::atomic_int failures{0}, successes{0};

{
std::vector<std::thread> threads;
for (int i = 0; i < 100; i++) {
threads.emplace_back([&]() {
EXPECT_THROW((dali::call_once(once, [&]() {
++failures;
throw std::runtime_error("test");
})), std::runtime_error);
});
}
for (auto &t : threads)
t.join();
}
EXPECT_EQ(failures.load(), 100);

{
std::vector<std::thread> threads;
for (int i = 0; i < 100; i++) {
threads.emplace_back([&]() {
dali::call_once(once, [&]() {
++successes;
});
});
}
for (auto &t : threads)
t.join();
}

EXPECT_EQ(successes.load(), 1);
}

} // namespace dali
13 changes: 6 additions & 7 deletions dali/kernels/imgproc/resample/resampling_filters.cu
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2019-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// Copyright (c) 2019-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -170,12 +170,11 @@ std::shared_ptr<ResamplingFilters> GetResamplingFilters() {

std::shared_ptr<ResamplingFilters> GetResamplingFiltersCPU() {
(void)mm::GetDefaultResource<mm::memory_kind::host>();
static std::once_flag once;
static std::shared_ptr<ResamplingFilters> cpu_filters;
std::call_once(once, []() {
cpu_filters = std::make_shared<ResamplingFilters>();
InitFilters<mm::memory_kind::host>(*cpu_filters);
});
static std::shared_ptr<ResamplingFilters> cpu_filters = []() {
auto filters = std::make_shared<ResamplingFilters>();
InitFilters<mm::memory_kind::host>(*filters);
return filters;
}();
return cpu_filters;
}

Expand Down
13 changes: 2 additions & 11 deletions dali/operators/image/resize/resampling_attr.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2019-2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// Copyright (c) 2019-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -15,6 +15,7 @@
#include "dali/operators/image/resize/resampling_attr.h"
#include "dali/pipeline/operator/common.h"
#include "dali/core/span.h"
#include "dali/core/call_once.h"

namespace dali {

Expand Down Expand Up @@ -93,16 +94,6 @@ void ResamplingFilterAttr::PrepareFilterParams(
}
return false;
};
if ((has_min && is_linear_default(make_cspan(min_arg_))) ||
(has_interp && is_linear_default(make_cspan(interp_type_arg_)))) {
static std::once_flag linear_default_warning_flag;
std::call_once(linear_default_warning_flag, [&]() {
DALI_WARN(
"The default behavior for LINEAR interpolation type has been changed to apply an "
"antialiasing filter. If you didn't mean to apply an antialiasing filter, please use "
"`antialias=False`");
});
}
}
Comment on lines -96 to -105
Copy link
Contributor Author

@mzient mzient Aug 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This warning was sitting here for 2 years now. Nobody complained during that time and the behavior is hardly a "change" any more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have mixed filling about including this in this particular PR. But up to you.


min_filter_.resize(num_samples, ResamplingFilterType::Triangular);
Expand Down
7 changes: 4 additions & 3 deletions dali/operators/imgcodec/image_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,19 +120,20 @@ inline int static_dali_pinned_free(void *ctx, void *ptr, size_t size, cudaStream
}

inline void get_nvimgcodec_version(int* major, int *minor, int* patch) {
static std::once_flag version_check_done;
static int s_major = -1, s_minor = -1, s_patch = -1;
auto version_check_f = [&] {
nvimgcodecProperties_t properties{NVIMGCODEC_STRUCTURE_TYPE_PROPERTIES,
sizeof(nvimgcodecProperties_t), 0};
if (NVIMGCODEC_STATUS_SUCCESS != nvimgcodecGetProperties(&properties))
return;
return 0;
int version = static_cast<int>(properties.version);
s_major = NVIMGCODEC_MAJOR_FROM_SEMVER(version);
s_minor = NVIMGCODEC_MINOR_FROM_SEMVER(version);
s_patch = NVIMGCODEC_PATCH_FROM_SEMVER(version);
return 0;
};
std::call_once(version_check_done, version_check_f);
static int version_check_done = version_check_f();
(void)version_check_done;
if (s_major == -1 || s_minor == -1 || s_patch == -1)
throw std::runtime_error("Failed to check nvImageCodec version");
*major = s_major;
Expand Down
5 changes: 3 additions & 2 deletions dali/operators/reader/loader/loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <atomic>
#include <unordered_set>

#include "dali/core/call_once.h"
#include "dali/core/nvtx.h"
#include "dali/core/common.h"
#include "dali/core/error_handling.h"
Expand Down Expand Up @@ -469,7 +470,7 @@ class Loader {
// Fetch image cache factory only the first time that we try to load an image
// we don't do it in construction because we are not sure that the cache was
// created since the order of operator creation is not guaranteed.
std::call_once(fetch_cache_, [this](){
dali::call_once(fetch_cache_, [this](){
auto &image_cache_factory = ImageCacheFactory::Instance();
if (image_cache_factory.IsInitialized(device_id_))
cache_ = image_cache_factory.Get(device_id_);
Expand Down Expand Up @@ -553,7 +554,7 @@ class Loader {
bool loading_flag_;

// Image cache
std::once_flag fetch_cache_;
dali::once_flag fetch_cache_;
std::shared_ptr<ImageCache> cache_;

// Counts how many samples the reader have read returned in the current epoch (including padding)
Expand Down
3 changes: 2 additions & 1 deletion dali/operators/reader/loader/webdataset_loader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "dali/operators/reader/loader/webdataset/tar_utils.h"
#include "dali/pipeline/data/types.h"
#include "dali/util/uri.h"
#include "dali/core/call_once.h"

namespace dali {

Expand Down Expand Up @@ -447,7 +448,7 @@ void WebdatasetLoader::PrepareMetadataImpl() {
component.outputs.num++;
was_output_set[output] = true;
} else {
std::call_once(multiple_files_single_component, [&]() {
dali::call_once(multiple_files_single_component, [&]() {
DALI_WARN(make_string("Multiple components matching output ", output, " at ",
GetSampleSource(new_sample), "."));
});
Expand Down
5 changes: 3 additions & 2 deletions dali/operators/reader/loader/webdataset_loader.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2021, 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// Copyright (c) 2021-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -23,6 +23,7 @@
#include <unordered_set>
#include <utility>
#include <vector>
#include "dali/core/call_once.h"
#include "dali/core/bitmask.h"
#include "dali/operators/reader/loader/loader.h"
#include "dali/pipeline/data/tensor.h"
Expand Down Expand Up @@ -117,7 +118,7 @@ class DLL_PUBLIC WebdatasetLoader : public Loader<CPUBackend, vector<Tensor<CPUB
std::vector<std::unique_ptr<FileStream>> wds_shards_;
size_t sample_index_ = 0;
FileStream::MappingReserver mmap_reserver_;
std::once_flag multiple_files_single_component;
dali::once_flag multiple_files_single_component;

bool generate_index_ = true;
std::string GetSampleSource(const detail::wds::SampleDesc& sample);
Expand Down
20 changes: 6 additions & 14 deletions dali/operators/sequence/optical_flow/optical_flow.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2019-2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// Copyright (c) 2019-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -145,18 +145,11 @@ class OpticalFlow : public StatelessOperator<Backend> {
*/
void of_lazy_init(size_t width, size_t height, size_t channels, DALIImageType image_type,
int device_id, cudaStream_t stream) {
std::call_once(of_initialized_,
[&]() {
optical_flow_.reset(
new optical_flow::OpticalFlowImpl(of_params_,
width,
height,
channels,
image_type,
device_id,
stream));
optical_flow_->Init(of_params_);
});
if (!optical_flow_) {
Comment on lines -148 to -159
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is called from within setup. No atomicity is required, setup is never called in parallel with itself.

optical_flow_ = std::make_unique<optical_flow::OpticalFlowImpl>(
of_params_, width, height, channels, image_type, device_id, stream);
optical_flow_->Init(of_params_);
}
}

/**
Expand Down Expand Up @@ -217,7 +210,6 @@ class OpticalFlow : public StatelessOperator<Backend> {
const int hint_grid_size_;
const bool enable_temporal_hints_;
const bool enable_external_hints_;
std::once_flag of_initialized_;
optical_flow::OpticalFlowParams of_params_;
std::unique_ptr<optical_flow::OpticalFlowAdapter<ComputeBackend>> optical_flow_;
DALIImageType image_type_;
Expand Down
13 changes: 6 additions & 7 deletions dali/test/dali_test_config.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
// Copyright (c) 2019-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -33,9 +33,7 @@ const std::string &dali_extra_path() {
// There's a "leak" here, but we don't really care about it.
static std::string *_dali_extra_path = new std::string();

static std::once_flag noninit_warning;

std::call_once(noninit_warning, []() {
static int noninit_warning = []() {
auto ptr = std::getenv("DALI_EXTRA_PATH");
if (!ptr) {
std::cerr << "WARNING: DALI_EXTRA_PATH not initialized." << std::endl;
Expand All @@ -51,7 +49,7 @@ const std::string &dali_extra_path() {
std::cerr << "WARNING: Could not read the sha of DALI_extra at " << *_dali_extra_path
<< ". Make sure DALI_EXTRA is checked out to " << DALI_EXTRA_VERSION
<< " so the test data is in the required version." << std::endl;
return;
return 0;
}
auto count = fread(hash, sizeof(hash[0]), kHashLen, pipe);
// hash is kHashLen + 1
Expand All @@ -61,15 +59,16 @@ const std::string &dali_extra_path() {
std::cerr << "WARNING: Could not read the sha of DALI_extra at " << *_dali_extra_path
<< ". Make sure DALI_EXTRA is checked out to " << DALI_EXTRA_VERSION
<< " so the test data is in the required version." << std::endl;
return;
return 0;
}
if (strncmp(DALI_EXTRA_VERSION, hash, kHashLen) != 0) {
std::cerr << "WARNING: DALI_extra at " << *_dali_extra_path
<< " is in different version than one required by the tests. Some tests may "
"fail to run or produce incorrect results.\nVersion required: "
<< DALI_EXTRA_VERSION << "\nVersion found: " << hash << std::endl;
}
});
return 0;
}();
return *_dali_extra_path;
}

Expand Down
8 changes: 4 additions & 4 deletions dali/util/numpy.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -161,14 +161,14 @@ void ParseHeaderContents(HeaderData& target, const std::string &header) {
void CheckNpyVersion(char *token) {
int api_version = token[6];
if (api_version != 1) {
static std::once_flag unrecognized_version;
std::call_once(unrecognized_version, [&]() {
static int unrecognized_version = [&]() {
std::string actual_version =
(api_version == 2 || api_version == 3) ? "higher" : "unrecognized";
DALI_WARN(make_string(
"Expected file in NPY file format version 1. The provided file uses ", actual_version,
" version. Please note, DALI does not support structured NumPy arrays."));
});
return 0;
}();
}
}

Expand Down
6 changes: 3 additions & 3 deletions dali/util/s3_client_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ namespace dali {
struct S3ClientManager {
public:
static S3ClientManager& Instance() {
static std::once_flag once;
std::call_once(once, []() {
static int init = [&]() {
RunInitOrShutdown([&](int) { Aws::InitAPI(Aws::SDKOptions{}); });
});
return 0;
})();
// We want RunInitOrShutdown s_thread_pool_ to outlive s_manager_
static S3ClientManager s_manager_;
return s_manager_;
Expand Down
Loading
Loading