Skip to content
Merged
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
30 changes: 30 additions & 0 deletions examples/createInstance/include/createInstance.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#pragma once

#include <hicr/core/instance.hpp>
#include <hicr/core/instanceManager.hpp>
#include <hicr/core/topology.hpp>

/**
* Create new HiCR instances
*
* \param[in] instanceManager
* \param[in] instanceCount
* \param[in] topology
*/
void createInstances(HiCR::InstanceManager &instanceManager, size_t instanceCount, HiCR::Topology &topology)
{
auto instanceTemplate = instanceManager.createInstanceTemplate(topology);

for (size_t i = 0; i < instanceCount; i++)
{
auto instance = instanceManager.createInstance(*instanceTemplate);
printf("[Instance %lu] Create instance %lu\n", instanceManager.getCurrentInstance()->getId(), instance->getId());
}
}

/**
* Function that all the created instances should execute
*
* \param[in] instanceManager
*/
void workerFc(HiCR::InstanceManager &instanceManager) { printf("[Instance %lu] Hello World\n", instanceManager.getCurrentInstance()->getId()); }
12 changes: 12 additions & 0 deletions examples/createInstance/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
testSuite = [ 'examples', 'createInstance', 'local' ]
test_timeout = 60

includeDirs = include_directories(['include'])

if 'hwloc' in enabledBackends and 'pthreads' in enabledBackends
pthreads = executable('pthreads', [ 'source/pthreads.cpp'], include_directories: includeDirs, dependencies: hicrBuildDep )

if get_option('buildTests')
test('pthreads', pthreads, args : [ '10' ], timeout: test_timeout, suite: testSuite )
endif
endif
52 changes: 52 additions & 0 deletions examples/createInstance/source/pthreads.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include <cstdio>
#include <pthread.h>
#include <thread>

#include <hicr/backends/hwloc/topologyManager.hpp>
#include <hicr/backends/pthreads/instanceManager.hpp>

#include "../include/createInstance.hpp"

int main(int argc, char const *argv[])
{
// Check argvs
if (argc != 2) { HICR_THROW_RUNTIME("Pass the number of instances to create as argument"); }

// Get instance count
size_t instancesToCreate = std::atoi(argv[1]);

// Determine the root instance id
HiCR::Instance::instanceId_t rootInstanceId = pthread_self();

// Declare entrypoint
auto entrypoint = [&](HiCR::InstanceManager *parentInstanceManager) {
// Cast to pthread instance manager
auto p = dynamic_cast<HiCR::backend::pthreads::InstanceManager *>(parentInstanceManager);

// Fail if the casting is not successful
if (p == nullptr) { HICR_THROW_RUNTIME("Can not cast instance manager to a pthread-specific one"); }

// Create instance manager
auto createdInstanceManager = HiCR::backend::pthreads::InstanceManager(rootInstanceId, p->getEntrypoint());

// Run worker function
workerFc(createdInstanceManager);
};

// Create instance manager
auto instanceManager = HiCR::backend::pthreads::InstanceManager(rootInstanceId, entrypoint);

// Discover local topology
auto topologyManager = HiCR::backend::hwloc::TopologyManager::createDefault();
auto topology = topologyManager->queryTopology();

// Create the new instance
createInstances(instanceManager, instancesToCreate, topology);

// Finalize instance manager
instanceManager.finalize();

printf("Terminating execution\n");

return 0;
}
1 change: 1 addition & 0 deletions examples/meson.build
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
subdir('createInstance')
subdir('memcpy')
subdir('kernel')
subdir('topology')
Expand Down
61 changes: 61 additions & 0 deletions include/hicr/backends/pthreads/instance.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright 2025 Huawei Technologies Co., Ltd.
*
* 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.
*/

/**
* @file instance.hpp
* @brief This file implements the instance class for the Pthreads backend
* @author L. Terracciano
* @date 10/10/2025
*/

#pragma once

#include <pthread.h>
#include <memory>
#include <hicr/core/instance.hpp>

namespace HiCR::backend::pthreads
{

/**
* Implementation of the HiCR Instance
*/
class Instance : public HiCR::Instance
{
public:

/**
* Constructor
*
* \param[in] instanceId the id of the instance
* \param[in] rootInstanceId the id of root
*/
Instance(instanceId_t instanceId, instanceId_t rootInstanceId)
: HiCR::Instance(instanceId),
_rootInstanceId(rootInstanceId){};

~Instance() = default;

bool isRootInstance() const override { return getId() != _rootInstanceId; };

private:

/**
* Id of HiCR root instance
*/
instanceId_t _rootInstanceId;
};
} // namespace HiCR::backend::pthreads
168 changes: 168 additions & 0 deletions include/hicr/backends/pthreads/instanceManager.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/*
* Copyright 2025 Huawei Technologies Co., Ltd.
*
* 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.
*/

/**
* @file instanceManager.hpp
* @brief This file implements the instance manager class for the Pthreads backend
* @author L. Terracciano
* @date 10/10/2025
*/

#pragma once

#include <pthread.h>

#include <hicr/core/instanceManager.hpp>

#include "instance.hpp"

namespace HiCR::backend::pthreads
{

/**
* Type for the instance entrypoint function
*/
typedef std::function<void(InstanceManager *)> entryPoint_t;

/**
* Implementation of HiCR InstanceManager class. It creates new HiCR Instance using pthreads
*/
class InstanceManager final : public HiCR::InstanceManager
{
public:

/**
* Constructor
*
* \param[in] rootInstanceId Id of HiCR root Instance
* \param[in] entrypoint function executed by the Instances when created
*/
InstanceManager(Instance::instanceId_t rootInstanceId, entryPoint_t entrypoint)
: HiCR::InstanceManager(),
_rootInstanceId(rootInstanceId),
_entrypoint(entrypoint)
{
// Create and set current instance in the base class
setCurrentInstance(std::make_shared<Instance>(pthread_self(), _rootInstanceId));
}

~InstanceManager() override = default;

/**
* Create a new instance inside a pthread
*
* \param[in] instanceTemplate instance template used to create the instance
*
* \return a HiCR instance
*/
std::shared_ptr<HiCR::Instance> createInstanceImpl(const HiCR::InstanceTemplate instanceTemplate) override
{
// Storage for the new instance id
pthread_t newInstanceId;

// Launch a new pthread executing the entrypoint
auto status = pthread_create(&newInstanceId, nullptr, launchWrapper, this);
if (status != 0) { HICR_THROW_RUNTIME("Could not create instance thread. Error: %d", status); }

// Add to the pool of created pthreads
_createdThreads.insert(newInstanceId);

// Create a new HiCR instance
return std::make_shared<Instance>(newInstanceId, _rootInstanceId);
}

/**
* Add an instance.
*
* \param[in] instanceId Id of the instance
*
* \return a HiCR instance
*/
std::shared_ptr<HiCR::Instance> addInstanceImpl(Instance::instanceId_t instanceId) override { return std::make_shared<Instance>(instanceId, _rootInstanceId); }

/**
* Terminate an instance. Nothing to do other than waiting for the pthread to finish
*
* \param[in] instance instance to terminate
*/
void terminateInstanceImpl(const std::shared_ptr<HiCR::Instance> instance) override
{
// Nothing to do here
}

/**
* Wait for all created threads to finalize
*/
void finalize() override
{
for (auto thread : _createdThreads) { pthread_join(thread, nullptr); }
}

/**
* Abort execution
*
* \param[in] errorCode exit code
*/
void abort(int errorCode) override { exit(errorCode); }

/**
* Getter for root instance id
*
* \return root instance id
*/
HiCR::Instance::instanceId_t getRootInstanceId() const override { return _rootInstanceId; }

/**
* Getter for the entrypoint. Useful if the intention is to
* propagate the same entrypoint across instance managers
*
* \return the entrypoint function
*/
entryPoint_t getEntrypoint() const { return _entrypoint; }

private:

/**
* Wrapper to launch the entrypoint of the new instance
*
* \param[in] parentInstanceManager instance manager of the creator instance
*/
__INLINE__ static void *launchWrapper(void *parentInstanceManager)
{
// Cast to a Pthread InstanceManager
auto p = static_cast<InstanceManager *>(parentInstanceManager);

// Run the entrypoint
p->_entrypoint(p);
return 0;
}

/**
* Id of the HiCR root Instance
*/
HiCR::Instance::instanceId_t _rootInstanceId;

/**
* Function that each newly created instance runs
*/
entryPoint_t _entrypoint;

/**
* Pool of threads created by the Instance Manager
*/
std::unordered_set<pthread_t> _createdThreads;
};
} // namespace HiCR::backend::pthreads
3 changes: 2 additions & 1 deletion include/hicr/backends/pthreads/sharedMemory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class SharedMemory
pthread_mutex_destroy(&_mutex);
}

// Disable object copy
SharedMemory(const SharedMemory &) = delete;
SharedMemory &operator=(const SharedMemory &) = delete;
SharedMemory(SharedMemory &&) = delete;
Expand Down Expand Up @@ -214,7 +215,7 @@ class SharedMemory
pthread_barrier_t _barrier{};

/**
* A mutex to make sure threads do not bother each other during certain operations.
* Mutex to enable thread safety in the class.
* Mutability allows const getter functions to lock the mutex, because this does not modify the logical
* state of the shared memory
*/
Expand Down
Loading