our_knp/examples/knp/tests/backend/cuda/cuda_bus_test.cu
int 8f43927575 Initial import: KNP experiments (examples, viz, cats-dogs, reports)
examples/ is based on KasperskyLab/knp at 55470ed6 with local changes
to the mnist-learn altai/blifat models, cuda-backend CMake and model_loader.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:17:15 +03:00

158 lines
6.6 KiB
Text

/**
* @file cuda_bus_test.cu
* @brief CUDA backend test.
* @kaspersky_support Vartenkov An.
* @date 08.09.2025
* @license Apache 2.0
* @copyright © 2025 AO Kaspersky Lab
*
* 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 <knp/core/message_bus.h>
#include <knp/core/population.h>
#include <knp/core/projection.h>
#include <generators.h>
#include <spdlog/spdlog.h>
#include <tests_common.h>
#include <functional>
#include <iostream>
#include <vector>
#include "../../../backends/gpu/cuda-backend/impl/backend_impl.cuh"
#include "../../../backends/gpu/cuda-backend/impl/cuda_lib/extraction.cuh"
#include "../../../backends/gpu/cuda-backend/impl/cuda_lib/register_type.cuh"
#include "../../../backends/gpu/cuda-backend/impl/cuda_lib/safe_call.cuh"
#include "../../../backends/gpu/cuda-backend/impl/cuda_lib/vector.cuh"
#include "../../../backends/gpu/cuda-backend/impl/cuda_bus/message_bus.cuh"
#include "../../../backends/gpu/cuda-backend/impl/cuda_bus/messaging.cuh"
#include "../../../backends/gpu/cuda-backend/impl/uid.cuh"
#include "../../../backends/gpu/cuda-backend/impl/projection.cuh"
#include "../../../backends/gpu/cuda-backend/impl/population.cuh"
REGISTER_CUDA_VECTOR_TYPE(unsigned long long);
REGISTER_CUDA_VECTOR_TYPE(unsigned long);
REGISTER_CUDA_VECTOR_TYPE(unsigned int);
REGISTER_CUDA_VECTOR_TYPE(knp::backends::gpu::cuda::UID);
REGISTER_CUDA_VECTOR_TYPE(knp::backends::gpu::cuda::Subscription);
REGISTER_CUDA_VECTOR_TYPE(knp::backends::gpu::cuda::PopulationVariants);
REGISTER_CUDA_VECTOR_TYPE(knp::backends::gpu::cuda::ProjectionVariants);
REGISTER_CUDA_VECTOR_TYPE(knp::backends::gpu::cuda::SpikeMessage);
REGISTER_CUDA_VECTOR_TYPE(knp::backends::gpu::cuda::SynapticImpact);
REGISTER_CUDA_VECTOR_TYPE(knp::backends::gpu::cuda::SynapticImpactMessage);
REGISTER_CUDA_VECTOR_TYPE(knp::backends::gpu::cuda::MessageVariant);
REGISTER_CUDA_VECTOR_TYPE(knp::backends::gpu::cuda::CUDAProjection<knp::synapse_traits::DeltaSynapse>::Synapse);
REGISTER_CUDA_VECTOR_TYPE(knp::backends::gpu::cuda::CUDAPopulation<knp::neuron_traits::BLIFATNeuron>::NeuronParameters);
namespace knp::testing
{
struct MessageBusTandem
{
MessageBusTandem() :
cpu_(std::move(*knp::core::MessageBus::construct_bus())),
endpoint_(cpu_.create_endpoint()),
gpu_(endpoint_)
{}
knp::core::MessageBus cpu_;
knp::core::MessageEndpoint endpoint_;
knp::backends::gpu::cuda::CUDAMessageBus gpu_;
};
TEST(CudaBackendSuite, MessagesTest)
{
namespace knp_cuda = knp::backends::gpu::cuda;
knp_cuda::SpikeMessage message_1;
knp_cuda::SynapticImpactMessage message_2;
ASSERT_EQ(message_1.neuron_indexes_.size(), 0);
ASSERT_EQ(message_2.impacts_.size(), 0);
}
TEST(CudaBackendSuite, CudaHostSubscription)
{
namespace knp_cuda = knp::backends::gpu::cuda;
call_and_check(cudaDeviceReset());
knp_cuda::UID receiver_uid = knp_cuda::to_gpu_uid(knp::core::UID{});
knp_cuda::UID sender_1 = knp_cuda::to_gpu_uid(knp::core::UID{}), sender_2 = knp_cuda::to_gpu_uid(knp::core::UID{});
knp_cuda::UID sender_3 = knp_cuda::to_gpu_uid(knp::core::UID{}), sender_4 = knp_cuda::to_gpu_uid(knp::core::UID{});
ASSERT_NE(sender_1, sender_2);
auto type_index = boost::mp11::mp_find<knp_cuda::MessageVariant, knp_cuda::SpikeMessage>();
knp_cuda::Subscription subscription(receiver_uid, std::vector{sender_1, sender_2, sender_3}, type_index);
ASSERT_EQ(subscription.get_senders().size(), 3);
ASSERT_TRUE(subscription.has_sender(sender_2));
ASSERT_FALSE(subscription.has_sender(sender_4));
}
TEST(CudaBackendSuite, BusSubscriptionsTest)
{
namespace knp_cuda = knp::backends::gpu::cuda;
MessageBusTandem message_buses;
knp_cuda::UID uid_1{knp_cuda::new_uid()}, uid_2{knp_cuda::new_uid()};
knp_cuda::UID uid_3{knp_cuda::new_uid()}, uid_4{knp_cuda::new_uid()};
std::vector<knp_cuda::UID> uid_vec1{uid_2, uid_3};
message_buses.gpu_.subscribe_gpu<knp_cuda::SpikeMessage>(uid_1, uid_vec1);
ASSERT_EQ(message_buses.gpu_.get_subscriptions().size(), 1);
std::cout << "Number of subscriptions is 1" << std::endl;
std::vector<knp_cuda::UID> uid_vec2{uid_3, uid_4};
message_buses.gpu_.subscribe_gpu<knp_cuda::SpikeMessage>(uid_2, uid_vec2);
std::cout << "Added subscription" << std::endl;
ASSERT_EQ(message_buses.gpu_.get_subscriptions().size(), 2);
std::cout << "Number of subscriptions is 2" << std::endl;
std::vector<knp_cuda::UID> uid_vec3{uid_1};
message_buses.gpu_.subscribe_gpu<knp_cuda::SpikeMessage>(uid_1, uid_vec3);
// TODO check corresponding subscription size, should become 3.
ASSERT_EQ(message_buses.gpu_.get_subscriptions().size(), 2);
std::cout << "Number of subscriptions is still 2" << std::endl;
// unsubscribing from a wrong type of messages, shouldn't change anything.
message_buses.gpu_.unsubscribe<knp_cuda::SynapticImpactMessage>(uid_1);
ASSERT_EQ(message_buses.gpu_.get_subscriptions().size(), 2);
std::cout << "Shouldn't have been deleted" << std::endl;
// now unsubscribing from the right type of messages.
message_buses.gpu_.unsubscribe<knp_cuda::SpikeMessage>(uid_1);
ASSERT_EQ(message_buses.gpu_.get_subscriptions().size(), 1);
}
TEST(CudaMessagingSuite, AddReceiveBusMessage)
{
namespace knp_cuda = knp::backends::gpu::cuda;
using SpikeMessage = knp_cuda::SpikeMessage;
MessageBusTandem message_buses;
SpikeMessage msg{{knp_cuda::new_uid()}, {1, 2, 3, 4, 5}};
knp_cuda::UID receiver_uid = knp_cuda::new_uid();
std::vector<knp_cuda::UID> senders{msg.header_.sender_uid_};
message_buses.gpu_.subscribe_gpu<SpikeMessage>(receiver_uid, {msg.header_.sender_uid_});
EXPECT_EQ(message_buses.gpu_.unload_messages<SpikeMessage>(receiver_uid).size(), 0);
message_buses.gpu_.send_message(std::move(msg));
EXPECT_EQ(message_buses.gpu_.unload_messages<SpikeMessage>(receiver_uid).size(), 1);
EXPECT_EQ(message_buses.gpu_.unload_messages<knp_cuda::SynapticImpactMessage>(receiver_uid).size(), 0);
EXPECT_EQ(message_buses.gpu_.unload_messages<SpikeMessage>(msg.header_.sender_uid_).size(), 0);
message_buses.gpu_.clear();
EXPECT_EQ(message_buses.gpu_.unload_messages<SpikeMessage>(receiver_uid).size(), 0);
}
} // namespace knp::testing