Embedded
- C++ kursu
- Uzman
- Ders 46/47
- 6 dk
Gömülü kısıtlarla optimize edilmiş kod yazarsın.
volatile ve bellek eşlemeli I/O
Bellek eşlemeli I/O (MMIO), donanım kayıtlarının normal bellek adreslerinde görünmesidir. Bir kaydı okumak için o adresteki değeri okuruz. volatile anahtar kelimesi derleyiciye "her okumada bellekten oku, önbelleğe alma" der.
Örnek: volatile std::uint32_t* reg bir donanım kaydına işaret eder. *reg = 64; yazma, *reg okuma yapar. Derleyici bu erişimleri atlayamaz. Bu derste volatile std::uint32_t değişkenini bir sahte kayıt olarak kullanıp MMIO desenini öğreneceğiz.
Derleyici optimizasyonu ve volatile
Derleyici en iyileyici (optimizer), bir değişkeni birden çok kez okuduğunda önceki sonucu yeniden kullanabilir. Normal bir değişkende bu güvenlidir; çünkü değer program tarafından değişmedikçe aynı kalır. Donanım kaydında ise değer program dışında değişebilir; önbelleğe alınmış okuma yanlış olur.
volatile bu optimizasyonu kapatır. Her *reg okuması belleğe gider. Bu dersin örneğinde sahte kaydı 64 değeriyle yazar, sonra geri okuruz. Sonuç 64 olur; volatile sayesinde okuma atlanmaz.
Uygulama readRegister ve writeRegister metodlarını ekle
Önceki dersin çözümünü al (Engine sınıfında parallelSum var). Engine sınıfının public: bölümüne iki statik metot ekle: static std::uint32_t readRegister(volatile std::uint32_t* reg) gövdesi return *reg;, static void writeRegister(volatile std::uint32_t* reg, std::uint32_t value) gövdesi *reg = value;. main içinde parallelSum çağrısından sonra şunları ekle: volatile std::uint32_t reg = 0;, Engine::writeRegister(®, 64);, std::cout << std::endl << Engine::readRegister(®);. #include <cstdint> gereklidir.
Başlangıç kodu
#include <iostream>
#include <atomic>
#include <thread>
#include <cstdint>
class Engine {
public:
static const int Version = 1;
static int parallelSum() {
std::atomic<int> total{0};
std::thread t1([&]() { for (int i = 1; i <= 4; ++i) total += i; });
std::thread t2([&]() { for (int i = 5; i <= 8; ++i) total += i; });
t1.join();
t2.join();
return total.load();
}
// readRegister ve writeRegister buraya ekle
};
template <int N>
struct Factorial {
static const int value = N * Factorial<N - 1>::value;
};
template <>
struct Factorial<0> {
static const int value = 1;
};
int main() {
std::cout << "Hazır" << std::endl;
std::cout << Factorial<5>::value << std::endl;
std::cout << Engine::parallelSum() << std::endl;
// Kayıt erişimini buraya ekle
return 0;
}Örnek çözüm
#include <iostream>
#include <atomic>
#include <thread>
#include <cstdint>
class Engine {
public:
static const int Version = 1;
static int parallelSum() {
std::atomic<int> total{0};
std::thread t1([&]() { for (int i = 1; i <= 4; ++i) total += i; });
std::thread t2([&]() { for (int i = 5; i <= 8; ++i) total += i; });
t1.join();
t2.join();
return total.load();
}
static std::uint32_t readRegister(volatile std::uint32_t* reg) {
return *reg;
}
static void writeRegister(volatile std::uint32_t* reg, std::uint32_t value) {
*reg = value;
}
};
template <int N>
struct Factorial {
static const int value = N * Factorial<N - 1>::value;
};
template <>
struct Factorial<0> {
static const int value = 1;
};
int main() {
std::cout << "Hazır" << std::endl;
std::cout << Factorial<5>::value << std::endl;
std::cout << Engine::parallelSum() << std::endl;
volatile std::uint32_t reg = 0;
Engine::writeRegister(®, 64);
std::cout << Engine::readRegister(®);
return 0;
}Beklenen çıktı
Hazır 120 36 64
Soru ve cevaplar
Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.
1 Kayıt işaretçisini tamamla
std::uint32_t readRegister(volatile std::uint32_t* ____) { return *reg; }
std::uint32_t readRegister(volatile std::uint32_t* reg) { return *reg; }
Açıklama: İşaretçi adı reg olarak kullanılır.
2 Parçayı rolüne eşle
| Kavram | Anlamı |
|---|---|
volatile |
Optimizasyonu kapatır |
std::uint32_t* |
Kayıt işaretçisi |
*reg = 64 |
Kayda yazma |
*reg |
Kayıttan okuma |
3 volatile anahtar kelimesi ne işe yarar?
volatile std::uint32_t* reg;- Değişkeni sabit yapar
- Derleyiciye okumayı atlamamasını söyler Doğru cevap
- Değişkeni otomatik sıfırlar
- Değişkeni iş parçacığı yerel yapar
Açıklama: volatile her okumayı belleğe zorlar; önbelleğe almaz.